diff --git a/.github/workflows/gitleaks-auto-redact.yml b/.github/workflows/gitleaks-auto-redact.yml
index f48eb990..a38d464f 100644
--- a/.github/workflows/gitleaks-auto-redact.yml
+++ b/.github/workflows/gitleaks-auto-redact.yml
@@ -23,7 +23,7 @@ permissions:
jobs:
auto-redact:
- runs-on: ubuntu-latest
+ runs-on: ubuntu-24.04
# A fork PR's checkout token can't push back to someone else's fork -
# GitHub blocks that regardless of what token this job holds - so skip
# cleanly rather than fail noisily. This job only ever adds a
diff --git a/.github/workflows/pr-flowvault.yml b/.github/workflows/pr-flowvault.yml
index 5b44ed35..69630dbf 100644
--- a/.github/workflows/pr-flowvault.yml
+++ b/.github/workflows/pr-flowvault.yml
@@ -16,7 +16,7 @@ on:
jobs:
build:
name: Build
- runs-on: ubuntu-latest
+ runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v2
@@ -40,7 +40,7 @@ jobs:
test:
name: Unit Tests
- runs-on: ubuntu-latest
+ runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v2
@@ -85,7 +85,7 @@ jobs:
smoke:
name: Clean-install smoke test
- runs-on: ubuntu-latest
+ runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v2
diff --git a/.github/workflows/shared-tests.yml b/.github/workflows/shared-tests.yml
index 8d73cdfa..ef1f3884 100644
--- a/.github/workflows/shared-tests.yml
+++ b/.github/workflows/shared-tests.yml
@@ -10,7 +10,7 @@ on:
jobs:
run-tests:
- runs-on: ubuntu-latest
+ runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
diff --git a/.gitignore b/.gitignore
index cceb4f18..897fb694 100644
--- a/.gitignore
+++ b/.gitignore
@@ -132,4 +132,7 @@ dmypy.json
# Misc
test.py
credentials.json
-example.py
\ No newline at end of file
+example.py
+
+# Local-only detect sample runs (credentials + recorded outputs, never committed)
+flowvault/samples/detect_api_local/
\ No newline at end of file
diff --git a/README.md b/README.md
index d6015b5d..22844bfd 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@ This repository hosts Skyflow's Python SDKs for integrating Skyflow into a Pytho
> **Install one per environment.** Both artifacts install under the same top-level `skyflow` import, so they cannot coexist in the same Python environment.
-> Migrating from v1? See skyvault's **[Migration Guide](docs/migrate_to_v2.md)**. V1 is in maintenance mode and will reach End of Life on October 31, 2026.
+> :warning: **skyflow-python v1 reached End of Life on October 31, 2026 and is no longer supported.** It will not receive any further security patches, bug fixes, or updates. Please upgrade to the latest skyflow-python v2 ([2.1.3](https://github.com/skyflowapi/skyflow-python/releases/tag/2.1.3)) using the **[Migration Guide](docs/migrate_to_v2.md)**.
## Repository layout
diff --git a/common/generated/rest/__init__.py b/common/generated/rest/__init__.py
index 2b7e1ccf..c12478f4 100644
--- a/common/generated/rest/__init__.py
+++ b/common/generated/rest/__init__.py
@@ -2,23 +2,239 @@
# isort: skip_file
-from .types import GooglerpcStatus, ProtobufAny, V1GetAuthTokenResponse
-from .errors import BadRequestError, NotFoundError, UnauthorizedError
-from . import authentication
-from .client import AsyncSkyflowAuth, SkyflowAuth
-from .environment import SkyflowAuthEnvironment
-from .version import __version__
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .types import (
+ AudioV2,
+ AudioV2Bleep,
+ AudioV2OutputTranscription,
+ DeidentifyFileResponseV2,
+ DeidentifyStringResponseV2,
+ DeidentifyStringResponseV2DetectedEntity,
+ DeidentifyStringResponseV2EntityLocation,
+ Detect,
+ DetectConfigV2,
+ DetectConfigV2VaultType,
+ DetectCustomTypes,
+ DetectCustomTypesDeidentificationType,
+ DetectCustomTypesIncludePrefix,
+ DetectEntity,
+ DetectEntityDeidentificationType,
+ DetectEntityEntityType,
+ DetectEntityIncludePrefix,
+ DetectGuardrailsResponseV2,
+ DetectGuardrailsResponseV2Validation,
+ DetectObjectEntity,
+ DetectObjectEntityDeidentificationType,
+ DetectObjectEntityEntityType,
+ DetectReturnEntities,
+ DetectRunsResponseV2,
+ DetectRunsResponseV2OutputType,
+ DetectRunsResponseV2Status,
+ DocumentV2,
+ DocumentV2Pdf,
+ DocumentV2PdfProcessingMode,
+ EntityTransformation,
+ ErrorResponse,
+ ErrorResponseError,
+ FileMapping,
+ FileOutput,
+ FileOutputProcessedFileExtension,
+ FileOutputProcessedFileType,
+ GetAuthTokenResponse,
+ GetStsTokenResponse,
+ HttpCode,
+ ImageV2,
+ ImageV2MaskingMethod,
+ Media,
+ Metrics,
+ RedactionLevel,
+ RedactionLevelEntityName,
+ RedactionLevelRedactionType,
+ ReidentifyFileResponseV2,
+ ReidentifyFileResponseV2OutputType,
+ ReidentifyFileResponseV2Status,
+ ReidentifyStringResponseV2,
+ TransformationShiftDates,
+ )
+ from .errors import BadRequestError, InternalServerError, NotFoundError, UnauthorizedError
+ from . import authentication, files_v2, guardrails_v2, strings_v2, token_exchange
+ from ._default_clients import DefaultAioHttpClient, DefaultAsyncHttpxClient
+ from .client import AsyncSkyflowAuth, SkyflowAuth
+ from .environment import SkyflowAuthEnvironment
+ from .files_v2 import (
+ DeidentifyFileRequestV2DataFormat,
+ DeidentifyFileRequestV2DataSource,
+ ReidentifyFileRequestV2DataFormat,
+ ReidentifyFileRequestV2DataSource,
+ )
+ from .version import __version__
+_dynamic_imports: typing.Dict[str, str] = {
+ "AsyncSkyflowAuth": ".client",
+ "AudioV2": ".types",
+ "AudioV2Bleep": ".types",
+ "AudioV2OutputTranscription": ".types",
+ "BadRequestError": ".errors",
+ "DefaultAioHttpClient": "._default_clients",
+ "DefaultAsyncHttpxClient": "._default_clients",
+ "DeidentifyFileRequestV2DataFormat": ".files_v2",
+ "DeidentifyFileRequestV2DataSource": ".files_v2",
+ "DeidentifyFileResponseV2": ".types",
+ "DeidentifyStringResponseV2": ".types",
+ "DeidentifyStringResponseV2DetectedEntity": ".types",
+ "DeidentifyStringResponseV2EntityLocation": ".types",
+ "Detect": ".types",
+ "DetectConfigV2": ".types",
+ "DetectConfigV2VaultType": ".types",
+ "DetectCustomTypes": ".types",
+ "DetectCustomTypesDeidentificationType": ".types",
+ "DetectCustomTypesIncludePrefix": ".types",
+ "DetectEntity": ".types",
+ "DetectEntityDeidentificationType": ".types",
+ "DetectEntityEntityType": ".types",
+ "DetectEntityIncludePrefix": ".types",
+ "DetectGuardrailsResponseV2": ".types",
+ "DetectGuardrailsResponseV2Validation": ".types",
+ "DetectObjectEntity": ".types",
+ "DetectObjectEntityDeidentificationType": ".types",
+ "DetectObjectEntityEntityType": ".types",
+ "DetectReturnEntities": ".types",
+ "DetectRunsResponseV2": ".types",
+ "DetectRunsResponseV2OutputType": ".types",
+ "DetectRunsResponseV2Status": ".types",
+ "DocumentV2": ".types",
+ "DocumentV2Pdf": ".types",
+ "DocumentV2PdfProcessingMode": ".types",
+ "EntityTransformation": ".types",
+ "ErrorResponse": ".types",
+ "ErrorResponseError": ".types",
+ "FileMapping": ".types",
+ "FileOutput": ".types",
+ "FileOutputProcessedFileExtension": ".types",
+ "FileOutputProcessedFileType": ".types",
+ "GetAuthTokenResponse": ".types",
+ "GetStsTokenResponse": ".types",
+ "HttpCode": ".types",
+ "ImageV2": ".types",
+ "ImageV2MaskingMethod": ".types",
+ "InternalServerError": ".errors",
+ "Media": ".types",
+ "Metrics": ".types",
+ "NotFoundError": ".errors",
+ "RedactionLevel": ".types",
+ "RedactionLevelEntityName": ".types",
+ "RedactionLevelRedactionType": ".types",
+ "ReidentifyFileRequestV2DataFormat": ".files_v2",
+ "ReidentifyFileRequestV2DataSource": ".files_v2",
+ "ReidentifyFileResponseV2": ".types",
+ "ReidentifyFileResponseV2OutputType": ".types",
+ "ReidentifyFileResponseV2Status": ".types",
+ "ReidentifyStringResponseV2": ".types",
+ "SkyflowAuth": ".client",
+ "SkyflowAuthEnvironment": ".environment",
+ "TransformationShiftDates": ".types",
+ "UnauthorizedError": ".errors",
+ "__version__": ".version",
+ "authentication": ".authentication",
+ "files_v2": ".files_v2",
+ "guardrails_v2": ".guardrails_v2",
+ "strings_v2": ".strings_v2",
+ "token_exchange": ".token_exchange",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
__all__ = [
"AsyncSkyflowAuth",
+ "AudioV2",
+ "AudioV2Bleep",
+ "AudioV2OutputTranscription",
"BadRequestError",
- "GooglerpcStatus",
+ "DefaultAioHttpClient",
+ "DefaultAsyncHttpxClient",
+ "DeidentifyFileRequestV2DataFormat",
+ "DeidentifyFileRequestV2DataSource",
+ "DeidentifyFileResponseV2",
+ "DeidentifyStringResponseV2",
+ "DeidentifyStringResponseV2DetectedEntity",
+ "DeidentifyStringResponseV2EntityLocation",
+ "Detect",
+ "DetectConfigV2",
+ "DetectConfigV2VaultType",
+ "DetectCustomTypes",
+ "DetectCustomTypesDeidentificationType",
+ "DetectCustomTypesIncludePrefix",
+ "DetectEntity",
+ "DetectEntityDeidentificationType",
+ "DetectEntityEntityType",
+ "DetectEntityIncludePrefix",
+ "DetectGuardrailsResponseV2",
+ "DetectGuardrailsResponseV2Validation",
+ "DetectObjectEntity",
+ "DetectObjectEntityDeidentificationType",
+ "DetectObjectEntityEntityType",
+ "DetectReturnEntities",
+ "DetectRunsResponseV2",
+ "DetectRunsResponseV2OutputType",
+ "DetectRunsResponseV2Status",
+ "DocumentV2",
+ "DocumentV2Pdf",
+ "DocumentV2PdfProcessingMode",
+ "EntityTransformation",
+ "ErrorResponse",
+ "ErrorResponseError",
+ "FileMapping",
+ "FileOutput",
+ "FileOutputProcessedFileExtension",
+ "FileOutputProcessedFileType",
+ "GetAuthTokenResponse",
+ "GetStsTokenResponse",
+ "HttpCode",
+ "ImageV2",
+ "ImageV2MaskingMethod",
+ "InternalServerError",
+ "Media",
+ "Metrics",
"NotFoundError",
- "ProtobufAny",
+ "RedactionLevel",
+ "RedactionLevelEntityName",
+ "RedactionLevelRedactionType",
+ "ReidentifyFileRequestV2DataFormat",
+ "ReidentifyFileRequestV2DataSource",
+ "ReidentifyFileResponseV2",
+ "ReidentifyFileResponseV2OutputType",
+ "ReidentifyFileResponseV2Status",
+ "ReidentifyStringResponseV2",
"SkyflowAuth",
"SkyflowAuthEnvironment",
+ "TransformationShiftDates",
"UnauthorizedError",
- "V1GetAuthTokenResponse",
"__version__",
"authentication",
+ "files_v2",
+ "guardrails_v2",
+ "strings_v2",
+ "token_exchange",
]
diff --git a/common/generated/rest/_default_clients.py b/common/generated/rest/_default_clients.py
new file mode 100644
index 00000000..057d547f
--- /dev/null
+++ b/common/generated/rest/_default_clients.py
@@ -0,0 +1,32 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import httpx
+
+SDK_DEFAULT_TIMEOUT = 60
+
+try:
+ import httpx_aiohttp # type: ignore[import-not-found]
+except ImportError:
+
+ class DefaultAioHttpClient(httpx.AsyncClient): # type: ignore
+ def __init__(self, **kwargs: typing.Any) -> None:
+ raise RuntimeError(
+ "To use the aiohttp client, install the aiohttp extra: pip install skyflow.generated.rest[aiohttp]"
+ )
+
+else:
+
+ class DefaultAioHttpClient(httpx_aiohttp.HttpxAiohttpClient): # type: ignore
+ def __init__(self, **kwargs: typing.Any) -> None:
+ kwargs.setdefault("timeout", SDK_DEFAULT_TIMEOUT)
+ kwargs.setdefault("follow_redirects", True)
+ super().__init__(**kwargs)
+
+
+class DefaultAsyncHttpxClient(httpx.AsyncClient):
+ def __init__(self, **kwargs: typing.Any) -> None:
+ kwargs.setdefault("timeout", SDK_DEFAULT_TIMEOUT)
+ kwargs.setdefault("follow_redirects", True)
+ super().__init__(**kwargs)
diff --git a/common/generated/rest/authentication/client.py b/common/generated/rest/authentication/client.py
index 789b8760..d9b4309b 100644
--- a/common/generated/rest/authentication/client.py
+++ b/common/generated/rest/authentication/client.py
@@ -4,7 +4,7 @@
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.request_options import RequestOptions
-from ..types.v_1_get_auth_token_response import V1GetAuthTokenResponse
+from ..types.get_auth_token_response import GetAuthTokenResponse
from .raw_client import AsyncRawAuthenticationClient, RawAuthenticationClient
# this is used as the default value for optional parameters
@@ -26,7 +26,7 @@ def with_raw_response(self) -> RawAuthenticationClient:
"""
return self._raw_client
- def authentication_service_get_auth_token(
+ def get_bearer_token(
self,
*,
grant_type: str,
@@ -36,9 +36,9 @@ def authentication_service_get_auth_token(
requested_token_use: typing.Optional[str] = OMIT,
scope: typing.Optional[str] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> V1GetAuthTokenResponse:
+ ) -> GetAuthTokenResponse:
"""
-
Generates a Bearer Token to authenticate with Skyflow. This method doesn't require the Authorization header.
Note: For recommended ways to authenticate, see API authentication.
+ Generates a Bearer Token to authenticate with Skyflow.
Parameters
----------
@@ -46,7 +46,7 @@ def authentication_service_get_auth_token(
Grant type of the request. Set this to `urn:ietf:params:oauth:grant-type:jwt-bearer`.
assertion : str
- User-signed JWT token that contains the following fields:
iss: Issuer of the JWT.key: Unique identifier for the key.aud: Recipient the JWT is intended for.exp: Time the JWT expires.sub: Subject of the JWT.ctx: (Optional) Value for Context-aware authorization.
+ User-signed JWT token that contains the following fields: iss (Issuer), key (Unique identifier), aud (Recipient), exp (Expiry), sub (Subject), ctx (Optional context for context-aware authorization).
subject_token : typing.Optional[str]
Subject token.
@@ -58,15 +58,15 @@ def authentication_service_get_auth_token(
Token use type. Either `delegation` or `impersonation`.
scope : typing.Optional[str]
- Subset of available roles to associate with the requested token. Uses the format "role:\ role:\".
+ Subset of available roles to associate with the requested token. Uses the format "role: role:".
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- V1GetAuthTokenResponse
- A successful response.
+ GetAuthTokenResponse
+ OK
Examples
--------
@@ -75,12 +75,12 @@ def authentication_service_get_auth_token(
client = SkyflowAuth(
token="YOUR_TOKEN",
)
- client.authentication.authentication_service_get_auth_token(
- grant_type="urn:ietf:params:oauth:grant-type:jwt-bearer",
- assertion="",
+ client.authentication.get_bearer_token(
+ grant_type="grant_type",
+ assertion="assertion",
)
"""
- _response = self._raw_client.authentication_service_get_auth_token(
+ _response = self._raw_client.get_bearer_token(
grant_type=grant_type,
assertion=assertion,
subject_token=subject_token,
@@ -107,7 +107,7 @@ def with_raw_response(self) -> AsyncRawAuthenticationClient:
"""
return self._raw_client
- async def authentication_service_get_auth_token(
+ async def get_bearer_token(
self,
*,
grant_type: str,
@@ -117,9 +117,9 @@ async def authentication_service_get_auth_token(
requested_token_use: typing.Optional[str] = OMIT,
scope: typing.Optional[str] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> V1GetAuthTokenResponse:
+ ) -> GetAuthTokenResponse:
"""
- Generates a Bearer Token to authenticate with Skyflow. This method doesn't require the Authorization header.
Note: For recommended ways to authenticate, see API authentication.
+ Generates a Bearer Token to authenticate with Skyflow.
Parameters
----------
@@ -127,7 +127,7 @@ async def authentication_service_get_auth_token(
Grant type of the request. Set this to `urn:ietf:params:oauth:grant-type:jwt-bearer`.
assertion : str
- User-signed JWT token that contains the following fields:
iss: Issuer of the JWT.key: Unique identifier for the key.aud: Recipient the JWT is intended for.exp: Time the JWT expires.sub: Subject of the JWT.ctx: (Optional) Value for Context-aware authorization.
+ User-signed JWT token that contains the following fields: iss (Issuer), key (Unique identifier), aud (Recipient), exp (Expiry), sub (Subject), ctx (Optional context for context-aware authorization).
subject_token : typing.Optional[str]
Subject token.
@@ -139,15 +139,15 @@ async def authentication_service_get_auth_token(
Token use type. Either `delegation` or `impersonation`.
scope : typing.Optional[str]
- Subset of available roles to associate with the requested token. Uses the format "role:\ role:\".
+ Subset of available roles to associate with the requested token. Uses the format "role: role:".
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- V1GetAuthTokenResponse
- A successful response.
+ GetAuthTokenResponse
+ OK
Examples
--------
@@ -161,15 +161,15 @@ async def authentication_service_get_auth_token(
async def main() -> None:
- await client.authentication.authentication_service_get_auth_token(
- grant_type="urn:ietf:params:oauth:grant-type:jwt-bearer",
- assertion="",
+ await client.authentication.get_bearer_token(
+ grant_type="grant_type",
+ assertion="assertion",
)
asyncio.run(main())
"""
- _response = await self._raw_client.authentication_service_get_auth_token(
+ _response = await self._raw_client.get_bearer_token(
grant_type=grant_type,
assertion=assertion,
subject_token=subject_token,
diff --git a/common/generated/rest/authentication/raw_client.py b/common/generated/rest/authentication/raw_client.py
index bb1c2ed7..6e7d2c3b 100644
--- a/common/generated/rest/authentication/raw_client.py
+++ b/common/generated/rest/authentication/raw_client.py
@@ -6,12 +6,16 @@
from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.http_response import AsyncHttpResponse, HttpResponse
+from ..core.parse_error import ParsingError
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
from ..errors.bad_request_error import BadRequestError
+from ..errors.internal_server_error import InternalServerError
from ..errors.not_found_error import NotFoundError
from ..errors.unauthorized_error import UnauthorizedError
-from ..types.v_1_get_auth_token_response import V1GetAuthTokenResponse
+from ..types.error_response import ErrorResponse
+from ..types.get_auth_token_response import GetAuthTokenResponse
+from pydantic import ValidationError
# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)
@@ -21,7 +25,7 @@ class RawAuthenticationClient:
def __init__(self, *, client_wrapper: SyncClientWrapper):
self._client_wrapper = client_wrapper
- def authentication_service_get_auth_token(
+ def get_bearer_token(
self,
*,
grant_type: str,
@@ -31,9 +35,9 @@ def authentication_service_get_auth_token(
requested_token_use: typing.Optional[str] = OMIT,
scope: typing.Optional[str] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[V1GetAuthTokenResponse]:
+ ) -> HttpResponse[GetAuthTokenResponse]:
"""
- Generates a Bearer Token to authenticate with Skyflow. This method doesn't require the Authorization header.
Note: For recommended ways to authenticate, see API authentication.
+ Generates a Bearer Token to authenticate with Skyflow.
Parameters
----------
@@ -41,7 +45,7 @@ def authentication_service_get_auth_token(
Grant type of the request. Set this to `urn:ietf:params:oauth:grant-type:jwt-bearer`.
assertion : str
- User-signed JWT token that contains the following fields:
iss: Issuer of the JWT.key: Unique identifier for the key.aud: Recipient the JWT is intended for.exp: Time the JWT expires.sub: Subject of the JWT.ctx: (Optional) Value for Context-aware authorization.
+ User-signed JWT token that contains the following fields: iss (Issuer), key (Unique identifier), aud (Recipient), exp (Expiry), sub (Subject), ctx (Optional context for context-aware authorization).
subject_token : typing.Optional[str]
Subject token.
@@ -53,15 +57,15 @@ def authentication_service_get_auth_token(
Token use type. Either `delegation` or `impersonation`.
scope : typing.Optional[str]
- Subset of available roles to associate with the requested token. Uses the format "role:\ role:\".
+ Subset of available roles to associate with the requested token. Uses the format "role: role:".
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- HttpResponse[V1GetAuthTokenResponse]
- A successful response.
+ HttpResponse[GetAuthTokenResponse]
+ OK
"""
_response = self._client_wrapper.httpx_client.request(
"v1/auth/sa/oauth/token",
@@ -83,9 +87,9 @@ def authentication_service_get_auth_token(
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- V1GetAuthTokenResponse,
+ GetAuthTokenResponse,
parse_obj_as(
- type_=V1GetAuthTokenResponse, # type: ignore
+ type_=GetAuthTokenResponse, # type: ignore
object_=_response.json(),
),
)
@@ -94,9 +98,9 @@ def authentication_service_get_auth_token(
raise BadRequestError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Dict[str, typing.Optional[typing.Any]],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Dict[str, typing.Optional[typing.Any]], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -105,9 +109,9 @@ def authentication_service_get_auth_token(
raise UnauthorizedError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Dict[str, typing.Optional[typing.Any]],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Dict[str, typing.Optional[typing.Any]], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -116,9 +120,20 @@ def authentication_service_get_auth_token(
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Dict[str, typing.Optional[typing.Any]],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Dict[str, typing.Optional[typing.Any]], # type: ignore
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 500:
+ raise InternalServerError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -126,6 +141,10 @@ def authentication_service_get_auth_token(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
@@ -133,7 +152,7 @@ class AsyncRawAuthenticationClient:
def __init__(self, *, client_wrapper: AsyncClientWrapper):
self._client_wrapper = client_wrapper
- async def authentication_service_get_auth_token(
+ async def get_bearer_token(
self,
*,
grant_type: str,
@@ -143,9 +162,9 @@ async def authentication_service_get_auth_token(
requested_token_use: typing.Optional[str] = OMIT,
scope: typing.Optional[str] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[V1GetAuthTokenResponse]:
+ ) -> AsyncHttpResponse[GetAuthTokenResponse]:
"""
- Generates a Bearer Token to authenticate with Skyflow. This method doesn't require the Authorization header.
Note: For recommended ways to authenticate, see API authentication.
+ Generates a Bearer Token to authenticate with Skyflow.
Parameters
----------
@@ -153,7 +172,7 @@ async def authentication_service_get_auth_token(
Grant type of the request. Set this to `urn:ietf:params:oauth:grant-type:jwt-bearer`.
assertion : str
- User-signed JWT token that contains the following fields:
iss: Issuer of the JWT.key: Unique identifier for the key.aud: Recipient the JWT is intended for.exp: Time the JWT expires.sub: Subject of the JWT.ctx: (Optional) Value for Context-aware authorization.
+ User-signed JWT token that contains the following fields: iss (Issuer), key (Unique identifier), aud (Recipient), exp (Expiry), sub (Subject), ctx (Optional context for context-aware authorization).
subject_token : typing.Optional[str]
Subject token.
@@ -165,15 +184,15 @@ async def authentication_service_get_auth_token(
Token use type. Either `delegation` or `impersonation`.
scope : typing.Optional[str]
- Subset of available roles to associate with the requested token. Uses the format "role:\ role:\".
+ Subset of available roles to associate with the requested token. Uses the format "role: role:".
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- AsyncHttpResponse[V1GetAuthTokenResponse]
- A successful response.
+ AsyncHttpResponse[GetAuthTokenResponse]
+ OK
"""
_response = await self._client_wrapper.httpx_client.request(
"v1/auth/sa/oauth/token",
@@ -195,9 +214,9 @@ async def authentication_service_get_auth_token(
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- V1GetAuthTokenResponse,
+ GetAuthTokenResponse,
parse_obj_as(
- type_=V1GetAuthTokenResponse, # type: ignore
+ type_=GetAuthTokenResponse, # type: ignore
object_=_response.json(),
),
)
@@ -206,9 +225,9 @@ async def authentication_service_get_auth_token(
raise BadRequestError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Dict[str, typing.Optional[typing.Any]],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Dict[str, typing.Optional[typing.Any]], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -217,9 +236,9 @@ async def authentication_service_get_auth_token(
raise UnauthorizedError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Dict[str, typing.Optional[typing.Any]],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Dict[str, typing.Optional[typing.Any]], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -228,9 +247,20 @@ async def authentication_service_get_auth_token(
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Dict[str, typing.Optional[typing.Any]],
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 500:
+ raise InternalServerError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
parse_obj_as(
- type_=typing.Dict[str, typing.Optional[typing.Any]], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -238,4 +268,8 @@ async def authentication_service_get_auth_token(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/common/generated/rest/client.py b/common/generated/rest/client.py
index b210e4da..7123f423 100644
--- a/common/generated/rest/client.py
+++ b/common/generated/rest/client.py
@@ -1,11 +1,22 @@
# This file was auto-generated by Fern from our API Definition.
+from __future__ import annotations
+
import typing
import httpx
-from .authentication.client import AsyncAuthenticationClient, AuthenticationClient
from .core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .core.logging import LogConfig, Logger
+from .core.request_options import RequestOptions
from .environment import SkyflowAuthEnvironment
+from .raw_client import AsyncRawSkyflowAuth, RawSkyflowAuth
+
+if typing.TYPE_CHECKING:
+ from .authentication.client import AsyncAuthenticationClient, AuthenticationClient
+ from .files_v2.client import AsyncFilesV2Client, FilesV2Client
+ from .guardrails_v2.client import AsyncGuardrailsV2Client, GuardrailsV2Client
+ from .strings_v2.client import AsyncStringsV2Client, StringsV2Client
+ from .token_exchange.client import AsyncTokenExchangeClient, TokenExchangeClient
class SkyflowAuth:
@@ -26,6 +37,9 @@ class SkyflowAuth:
+ vault_url : typing.Optional[str]
+ Server URL variable for 'vault_url'. Defaults to '{{vault_url}}'.
+
token : typing.Optional[typing.Union[str, typing.Callable[[], str]]]
headers : typing.Optional[typing.Dict[str, str]]
Additional headers to send with every request.
@@ -33,12 +47,24 @@ class SkyflowAuth:
timeout : typing.Optional[float]
The timeout to be used, in seconds, for requests. By default the timeout is 60 seconds, unless a custom httpx client is used, in which case this default is not enforced.
+ max_retries : typing.Optional[int]
+ The default maximum number of retries for failed requests. Defaults to 2. Per-request `max_retries` in `request_options` takes precedence over this value.
+
+ stream_reconnection_enabled : typing.Optional[bool]
+ Whether to automatically reconnect on stream disconnection for resumable streaming endpoints. Defaults to True. Per-request `stream_reconnection_enabled` in `request_options` takes precedence over this value.
+
+ max_stream_reconnection_attempts : typing.Optional[int]
+ The maximum number of reconnection attempts for resumable streaming endpoints. Defaults to no limit. Per-request `max_stream_reconnection_attempts` in `request_options` takes precedence over this value.
+
follow_redirects : typing.Optional[bool]
Whether the default httpx client follows redirects or not, this is irrelevant if a custom httpx client is passed in.
httpx_client : typing.Optional[httpx.Client]
The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration.
+ logging : typing.Optional[typing.Union[LogConfig, Logger]]
+ Configure logging for the SDK. Accepts a LogConfig dict with 'level' (debug/info/warn/error), 'logger' (custom logger implementation), and 'silent' (boolean, defaults to True) fields. You can also pass a pre-configured Logger instance.
+
Examples
--------
from skyflow import SkyflowAuth
@@ -53,15 +79,28 @@ def __init__(
*,
base_url: typing.Optional[str] = None,
environment: SkyflowAuthEnvironment = SkyflowAuthEnvironment.PRODUCTION,
+ vault_url: typing.Optional[str] = None,
token: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = None,
headers: typing.Optional[typing.Dict[str, str]] = None,
timeout: typing.Optional[float] = None,
+ max_retries: typing.Optional[int] = None,
+ stream_reconnection_enabled: typing.Optional[bool] = None,
+ max_stream_reconnection_attempts: typing.Optional[int] = None,
follow_redirects: typing.Optional[bool] = True,
httpx_client: typing.Optional[httpx.Client] = None,
+ logging: typing.Optional[typing.Union[LogConfig, Logger]] = None,
):
- _defaulted_timeout = (
- timeout if timeout is not None else 60 if httpx_client is None else httpx_client.timeout.read
- )
+ _defaulted_timeout = timeout if timeout is not None else 60 if httpx_client is None else None
+ _defaulted_max_retries = max_retries if max_retries is not None else 2
+ if vault_url is not None:
+ _vault_url = vault_url if vault_url is not None else "{{vault_url}}"
+ _environment_url_templates = {
+ SkyflowAuthEnvironment.PRODUCTION: "https://{vault_url}",
+ SkyflowAuthEnvironment.SANDBOX: "https://{vault_url}",
+ }
+ _url_template = _environment_url_templates.get(environment, "https://{vault_url}")
+ if base_url is None:
+ base_url = _url_template.format(vault_url=_vault_url)
self._client_wrapper = SyncClientWrapper(
base_url=_get_base_url(base_url=base_url, environment=environment),
token=token,
@@ -72,8 +111,113 @@ def __init__(
if follow_redirects is not None
else httpx.Client(timeout=_defaulted_timeout),
timeout=_defaulted_timeout,
+ max_retries=_defaulted_max_retries,
+ stream_reconnection_enabled=stream_reconnection_enabled,
+ max_stream_reconnection_attempts=max_stream_reconnection_attempts,
+ logging=logging,
+ )
+ self._raw_client = RawSkyflowAuth(client_wrapper=self._client_wrapper)
+ self._authentication: typing.Optional[AuthenticationClient] = None
+ self._token_exchange: typing.Optional[TokenExchangeClient] = None
+ self._files_v2: typing.Optional[FilesV2Client] = None
+ self._strings_v2: typing.Optional[StringsV2Client] = None
+ self._guardrails_v2: typing.Optional[GuardrailsV2Client] = None
+
+ @property
+ def with_raw_response(self) -> RawSkyflowAuth:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawSkyflowAuth
+ """
+ return self._raw_client
+
+ def patch_v2vaults_id(
+ self, vault_id: typing.Optional[str], *, request_options: typing.Optional[RequestOptions] = None
+ ) -> None:
+ """
+ Parameters
+ ----------
+ vault_id : typing.Optional[str]
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ None
+
+ Examples
+ --------
+ from skyflow import SkyflowAuth
+
+ client = SkyflowAuth(
+ token="YOUR_TOKEN",
)
- self.authentication = AuthenticationClient(client_wrapper=self._client_wrapper)
+ client.patch_v2vaults_id()
+ """
+ _response = self._raw_client.patch_v2vaults_id(vault_id, request_options=request_options)
+ return _response.data
+
+ @property
+ def authentication(self):
+ if self._authentication is None:
+ from .authentication.client import AuthenticationClient # noqa: E402
+
+ self._authentication = AuthenticationClient(client_wrapper=self._client_wrapper)
+ return self._authentication
+
+ @property
+ def token_exchange(self):
+ if self._token_exchange is None:
+ from .token_exchange.client import TokenExchangeClient # noqa: E402
+
+ self._token_exchange = TokenExchangeClient(client_wrapper=self._client_wrapper)
+ return self._token_exchange
+
+ @property
+ def files_v2(self):
+ if self._files_v2 is None:
+ from .files_v2.client import FilesV2Client # noqa: E402
+
+ self._files_v2 = FilesV2Client(client_wrapper=self._client_wrapper)
+ return self._files_v2
+
+ @property
+ def strings_v2(self):
+ if self._strings_v2 is None:
+ from .strings_v2.client import StringsV2Client # noqa: E402
+
+ self._strings_v2 = StringsV2Client(client_wrapper=self._client_wrapper)
+ return self._strings_v2
+
+ @property
+ def guardrails_v2(self):
+ if self._guardrails_v2 is None:
+ from .guardrails_v2.client import GuardrailsV2Client # noqa: E402
+
+ self._guardrails_v2 = GuardrailsV2Client(client_wrapper=self._client_wrapper)
+ return self._guardrails_v2
+
+
+def _make_default_async_client(
+ timeout: typing.Optional[float],
+ follow_redirects: typing.Optional[bool],
+) -> httpx.AsyncClient:
+ try:
+ import httpx_aiohttp # type: ignore[import-not-found]
+ except ImportError:
+ pass
+ else:
+ if follow_redirects is not None:
+ return httpx_aiohttp.HttpxAiohttpClient(timeout=timeout, follow_redirects=follow_redirects)
+ return httpx_aiohttp.HttpxAiohttpClient(timeout=timeout)
+
+ if follow_redirects is not None:
+ return httpx.AsyncClient(timeout=timeout, follow_redirects=follow_redirects)
+ return httpx.AsyncClient(timeout=timeout)
class AsyncSkyflowAuth:
@@ -94,19 +238,37 @@ class AsyncSkyflowAuth:
+ vault_url : typing.Optional[str]
+ Server URL variable for 'vault_url'. Defaults to '{{vault_url}}'.
+
token : typing.Optional[typing.Union[str, typing.Callable[[], str]]]
headers : typing.Optional[typing.Dict[str, str]]
Additional headers to send with every request.
+ async_token : typing.Optional[typing.Callable[[], typing.Awaitable[str]]]
+ An async callable that returns a bearer token. Use this when token acquisition involves async I/O (e.g., refreshing tokens via an async HTTP client). When provided, this is used instead of the synchronous token for async requests.
+
timeout : typing.Optional[float]
The timeout to be used, in seconds, for requests. By default the timeout is 60 seconds, unless a custom httpx client is used, in which case this default is not enforced.
+ max_retries : typing.Optional[int]
+ The default maximum number of retries for failed requests. Defaults to 2. Per-request `max_retries` in `request_options` takes precedence over this value.
+
+ stream_reconnection_enabled : typing.Optional[bool]
+ Whether to automatically reconnect on stream disconnection for resumable streaming endpoints. Defaults to True. Per-request `stream_reconnection_enabled` in `request_options` takes precedence over this value.
+
+ max_stream_reconnection_attempts : typing.Optional[int]
+ The maximum number of reconnection attempts for resumable streaming endpoints. Defaults to no limit. Per-request `max_stream_reconnection_attempts` in `request_options` takes precedence over this value.
+
follow_redirects : typing.Optional[bool]
Whether the default httpx client follows redirects or not, this is irrelevant if a custom httpx client is passed in.
httpx_client : typing.Optional[httpx.AsyncClient]
The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration.
+ logging : typing.Optional[typing.Union[LogConfig, Logger]]
+ Configure logging for the SDK. Accepts a LogConfig dict with 'level' (debug/info/warn/error), 'logger' (custom logger implementation), and 'silent' (boolean, defaults to True) fields. You can also pass a pre-configured Logger instance.
+
Examples
--------
from skyflow import AsyncSkyflowAuth
@@ -121,27 +283,135 @@ def __init__(
*,
base_url: typing.Optional[str] = None,
environment: SkyflowAuthEnvironment = SkyflowAuthEnvironment.PRODUCTION,
+ vault_url: typing.Optional[str] = None,
token: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = None,
headers: typing.Optional[typing.Dict[str, str]] = None,
+ async_token: typing.Optional[typing.Callable[[], typing.Awaitable[str]]] = None,
timeout: typing.Optional[float] = None,
+ max_retries: typing.Optional[int] = None,
+ stream_reconnection_enabled: typing.Optional[bool] = None,
+ max_stream_reconnection_attempts: typing.Optional[int] = None,
follow_redirects: typing.Optional[bool] = True,
httpx_client: typing.Optional[httpx.AsyncClient] = None,
+ logging: typing.Optional[typing.Union[LogConfig, Logger]] = None,
):
- _defaulted_timeout = (
- timeout if timeout is not None else 60 if httpx_client is None else httpx_client.timeout.read
- )
+ _defaulted_timeout = timeout if timeout is not None else 60 if httpx_client is None else None
+ _defaulted_max_retries = max_retries if max_retries is not None else 2
+ if vault_url is not None:
+ _vault_url = vault_url if vault_url is not None else "{{vault_url}}"
+ _environment_url_templates = {
+ SkyflowAuthEnvironment.PRODUCTION: "https://{vault_url}",
+ SkyflowAuthEnvironment.SANDBOX: "https://{vault_url}",
+ }
+ _url_template = _environment_url_templates.get(environment, "https://{vault_url}")
+ if base_url is None:
+ base_url = _url_template.format(vault_url=_vault_url)
self._client_wrapper = AsyncClientWrapper(
base_url=_get_base_url(base_url=base_url, environment=environment),
token=token,
headers=headers,
+ async_token=async_token,
httpx_client=httpx_client
if httpx_client is not None
- else httpx.AsyncClient(timeout=_defaulted_timeout, follow_redirects=follow_redirects)
- if follow_redirects is not None
- else httpx.AsyncClient(timeout=_defaulted_timeout),
+ else _make_default_async_client(timeout=_defaulted_timeout, follow_redirects=follow_redirects),
timeout=_defaulted_timeout,
+ max_retries=_defaulted_max_retries,
+ stream_reconnection_enabled=stream_reconnection_enabled,
+ max_stream_reconnection_attempts=max_stream_reconnection_attempts,
+ logging=logging,
+ )
+ self._raw_client = AsyncRawSkyflowAuth(client_wrapper=self._client_wrapper)
+ self._authentication: typing.Optional[AsyncAuthenticationClient] = None
+ self._token_exchange: typing.Optional[AsyncTokenExchangeClient] = None
+ self._files_v2: typing.Optional[AsyncFilesV2Client] = None
+ self._strings_v2: typing.Optional[AsyncStringsV2Client] = None
+ self._guardrails_v2: typing.Optional[AsyncGuardrailsV2Client] = None
+
+ @property
+ def with_raw_response(self) -> AsyncRawSkyflowAuth:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawSkyflowAuth
+ """
+ return self._raw_client
+
+ async def patch_v2vaults_id(
+ self, vault_id: typing.Optional[str], *, request_options: typing.Optional[RequestOptions] = None
+ ) -> None:
+ """
+ Parameters
+ ----------
+ vault_id : typing.Optional[str]
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ None
+
+ Examples
+ --------
+ import asyncio
+
+ from skyflow import AsyncSkyflowAuth
+
+ client = AsyncSkyflowAuth(
+ token="YOUR_TOKEN",
)
- self.authentication = AsyncAuthenticationClient(client_wrapper=self._client_wrapper)
+
+
+ async def main() -> None:
+ await client.patch_v2vaults_id()
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.patch_v2vaults_id(vault_id, request_options=request_options)
+ return _response.data
+
+ @property
+ def authentication(self):
+ if self._authentication is None:
+ from .authentication.client import AsyncAuthenticationClient # noqa: E402
+
+ self._authentication = AsyncAuthenticationClient(client_wrapper=self._client_wrapper)
+ return self._authentication
+
+ @property
+ def token_exchange(self):
+ if self._token_exchange is None:
+ from .token_exchange.client import AsyncTokenExchangeClient # noqa: E402
+
+ self._token_exchange = AsyncTokenExchangeClient(client_wrapper=self._client_wrapper)
+ return self._token_exchange
+
+ @property
+ def files_v2(self):
+ if self._files_v2 is None:
+ from .files_v2.client import AsyncFilesV2Client # noqa: E402
+
+ self._files_v2 = AsyncFilesV2Client(client_wrapper=self._client_wrapper)
+ return self._files_v2
+
+ @property
+ def strings_v2(self):
+ if self._strings_v2 is None:
+ from .strings_v2.client import AsyncStringsV2Client # noqa: E402
+
+ self._strings_v2 = AsyncStringsV2Client(client_wrapper=self._client_wrapper)
+ return self._strings_v2
+
+ @property
+ def guardrails_v2(self):
+ if self._guardrails_v2 is None:
+ from .guardrails_v2.client import AsyncGuardrailsV2Client # noqa: E402
+
+ self._guardrails_v2 = AsyncGuardrailsV2Client(client_wrapper=self._client_wrapper)
+ return self._guardrails_v2
def _get_base_url(*, base_url: typing.Optional[str] = None, environment: SkyflowAuthEnvironment) -> str:
diff --git a/common/generated/rest/core/__init__.py b/common/generated/rest/core/__init__.py
index 31bbb818..5bc159a1 100644
--- a/common/generated/rest/core/__init__.py
+++ b/common/generated/rest/core/__init__.py
@@ -2,26 +2,91 @@
# isort: skip_file
-from .api_error import ApiError
-from .client_wrapper import AsyncClientWrapper, BaseClientWrapper, SyncClientWrapper
-from .datetime_utils import serialize_datetime
-from .file import File, convert_file_dict_to_httpx_tuples, with_content_type
-from .http_client import AsyncHttpClient, HttpClient
-from .http_response import AsyncHttpResponse, HttpResponse
-from .jsonable_encoder import jsonable_encoder
-from .pydantic_utilities import (
- IS_PYDANTIC_V2,
- UniversalBaseModel,
- UniversalRootModel,
- parse_obj_as,
- universal_field_validator,
- universal_root_validator,
- update_forward_refs,
-)
-from .query_encoder import encode_query
-from .remove_none_from_dict import remove_none_from_dict
-from .request_options import RequestOptions
-from .serialization import FieldMetadata, convert_and_respect_annotation_metadata
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .api_error import ApiError
+ from .client_wrapper import AsyncClientWrapper, BaseClientWrapper, SyncClientWrapper
+ from .datetime_utils import Rfc2822DateTime, parse_rfc2822_datetime, serialize_datetime
+ from .file import File, convert_file_dict_to_httpx_tuples, with_content_type
+ from .http_client import AsyncHttpClient, HttpClient
+ from .http_response import AsyncHttpResponse, HttpResponse
+ from .jsonable_encoder import encode_path_param, jsonable_encoder
+ from .logging import ConsoleLogger, ILogger, LogConfig, LogLevel, Logger, create_logger
+ from .parse_error import ParsingError
+ from .pydantic_utilities import (
+ IS_PYDANTIC_V2,
+ UniversalBaseModel,
+ UniversalRootModel,
+ parse_obj_as,
+ universal_field_validator,
+ universal_root_validator,
+ update_forward_refs,
+ )
+ from .query_encoder import encode_query
+ from .remove_none_from_dict import remove_none_from_dict
+ from .request_options import RequestOptions
+ from .serialization import FieldMetadata, convert_and_respect_annotation_metadata
+_dynamic_imports: typing.Dict[str, str] = {
+ "ApiError": ".api_error",
+ "AsyncClientWrapper": ".client_wrapper",
+ "AsyncHttpClient": ".http_client",
+ "AsyncHttpResponse": ".http_response",
+ "BaseClientWrapper": ".client_wrapper",
+ "ConsoleLogger": ".logging",
+ "FieldMetadata": ".serialization",
+ "File": ".file",
+ "HttpClient": ".http_client",
+ "HttpResponse": ".http_response",
+ "ILogger": ".logging",
+ "IS_PYDANTIC_V2": ".pydantic_utilities",
+ "LogConfig": ".logging",
+ "LogLevel": ".logging",
+ "Logger": ".logging",
+ "ParsingError": ".parse_error",
+ "RequestOptions": ".request_options",
+ "Rfc2822DateTime": ".datetime_utils",
+ "SyncClientWrapper": ".client_wrapper",
+ "UniversalBaseModel": ".pydantic_utilities",
+ "UniversalRootModel": ".pydantic_utilities",
+ "convert_and_respect_annotation_metadata": ".serialization",
+ "convert_file_dict_to_httpx_tuples": ".file",
+ "create_logger": ".logging",
+ "encode_path_param": ".jsonable_encoder",
+ "encode_query": ".query_encoder",
+ "jsonable_encoder": ".jsonable_encoder",
+ "parse_obj_as": ".pydantic_utilities",
+ "parse_rfc2822_datetime": ".datetime_utils",
+ "remove_none_from_dict": ".remove_none_from_dict",
+ "serialize_datetime": ".datetime_utils",
+ "universal_field_validator": ".pydantic_utilities",
+ "universal_root_validator": ".pydantic_utilities",
+ "update_forward_refs": ".pydantic_utilities",
+ "with_content_type": ".file",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
__all__ = [
"ApiError",
@@ -29,20 +94,30 @@
"AsyncHttpClient",
"AsyncHttpResponse",
"BaseClientWrapper",
+ "ConsoleLogger",
"FieldMetadata",
"File",
"HttpClient",
"HttpResponse",
+ "ILogger",
"IS_PYDANTIC_V2",
+ "LogConfig",
+ "LogLevel",
+ "Logger",
+ "ParsingError",
"RequestOptions",
+ "Rfc2822DateTime",
"SyncClientWrapper",
"UniversalBaseModel",
"UniversalRootModel",
"convert_and_respect_annotation_metadata",
"convert_file_dict_to_httpx_tuples",
+ "create_logger",
+ "encode_path_param",
"encode_query",
"jsonable_encoder",
"parse_obj_as",
+ "parse_rfc2822_datetime",
"remove_none_from_dict",
"serialize_datetime",
"universal_field_validator",
diff --git a/common/generated/rest/core/client_wrapper.py b/common/generated/rest/core/client_wrapper.py
index 9588d762..b4fbd425 100644
--- a/common/generated/rest/core/client_wrapper.py
+++ b/common/generated/rest/core/client_wrapper.py
@@ -4,6 +4,7 @@
import httpx
from .http_client import AsyncHttpClient, HttpClient
+from .logging import LogConfig, Logger
class BaseClientWrapper:
@@ -14,17 +15,29 @@ def __init__(
headers: typing.Optional[typing.Dict[str, str]] = None,
base_url: str,
timeout: typing.Optional[float] = None,
+ max_retries: int = 2,
+ stream_reconnection_enabled: typing.Optional[bool] = None,
+ max_stream_reconnection_attempts: typing.Optional[int] = None,
+ logging: typing.Optional[typing.Union[LogConfig, Logger]] = None,
):
self._token = token
self._headers = headers
self._base_url = base_url
self._timeout = timeout
+ self._max_retries = max_retries
+ self._stream_reconnection_enabled = stream_reconnection_enabled
+ self._max_stream_reconnection_attempts = max_stream_reconnection_attempts
+ self._logging = logging
def get_headers(self) -> typing.Dict[str, str]:
+ import platform
+
headers: typing.Dict[str, str] = {
"X-Fern-Language": "Python",
+ "X-Fern-Runtime": f"python/{platform.python_version()}",
+ "X-Fern-Platform": f"{platform.system().lower()}/{platform.release()}",
"X-Fern-SDK-Name": "skyflow.generated.rest",
- "X-Fern-SDK-Version": "0.0.9",
+ "X-Fern-SDK-Version": "0.0.45",
**(self.get_custom_headers() or {}),
}
token = self._get_token()
@@ -47,6 +60,15 @@ def get_base_url(self) -> str:
def get_timeout(self) -> typing.Optional[float]:
return self._timeout
+ def get_max_retries(self) -> int:
+ return self._max_retries
+
+ def get_stream_reconnection_enabled(self) -> bool:
+ return self._stream_reconnection_enabled if self._stream_reconnection_enabled is not None else True
+
+ def get_max_stream_reconnection_attempts(self) -> typing.Optional[int]:
+ return self._max_stream_reconnection_attempts
+
class SyncClientWrapper(BaseClientWrapper):
def __init__(
@@ -56,14 +78,29 @@ def __init__(
headers: typing.Optional[typing.Dict[str, str]] = None,
base_url: str,
timeout: typing.Optional[float] = None,
+ max_retries: int = 2,
+ stream_reconnection_enabled: typing.Optional[bool] = None,
+ max_stream_reconnection_attempts: typing.Optional[int] = None,
+ logging: typing.Optional[typing.Union[LogConfig, Logger]] = None,
httpx_client: httpx.Client,
):
- super().__init__(token=token, headers=headers, base_url=base_url, timeout=timeout)
+ super().__init__(
+ token=token,
+ headers=headers,
+ base_url=base_url,
+ timeout=timeout,
+ max_retries=max_retries,
+ stream_reconnection_enabled=stream_reconnection_enabled,
+ max_stream_reconnection_attempts=max_stream_reconnection_attempts,
+ logging=logging,
+ )
self.httpx_client = HttpClient(
httpx_client=httpx_client,
base_headers=self.get_headers,
base_timeout=self.get_timeout,
base_url=self.get_base_url,
+ base_max_retries=self.get_max_retries(),
+ logging_config=self._logging,
)
@@ -75,12 +112,37 @@ def __init__(
headers: typing.Optional[typing.Dict[str, str]] = None,
base_url: str,
timeout: typing.Optional[float] = None,
+ max_retries: int = 2,
+ stream_reconnection_enabled: typing.Optional[bool] = None,
+ max_stream_reconnection_attempts: typing.Optional[int] = None,
+ logging: typing.Optional[typing.Union[LogConfig, Logger]] = None,
+ async_token: typing.Optional[typing.Callable[[], typing.Awaitable[str]]] = None,
httpx_client: httpx.AsyncClient,
):
- super().__init__(token=token, headers=headers, base_url=base_url, timeout=timeout)
+ super().__init__(
+ token=token,
+ headers=headers,
+ base_url=base_url,
+ timeout=timeout,
+ max_retries=max_retries,
+ stream_reconnection_enabled=stream_reconnection_enabled,
+ max_stream_reconnection_attempts=max_stream_reconnection_attempts,
+ logging=logging,
+ )
+ self._async_token = async_token
self.httpx_client = AsyncHttpClient(
httpx_client=httpx_client,
base_headers=self.get_headers,
base_timeout=self.get_timeout,
base_url=self.get_base_url,
+ base_max_retries=self.get_max_retries(),
+ async_base_headers=self.async_get_headers,
+ logging_config=self._logging,
)
+
+ async def async_get_headers(self) -> typing.Dict[str, str]:
+ headers = self.get_headers()
+ if self._async_token is not None:
+ token = await self._async_token()
+ headers["Authorization"] = f"Bearer {token}"
+ return headers
diff --git a/common/generated/rest/core/datetime_utils.py b/common/generated/rest/core/datetime_utils.py
index 7c9864a9..a12b2ad0 100644
--- a/common/generated/rest/core/datetime_utils.py
+++ b/common/generated/rest/core/datetime_utils.py
@@ -1,6 +1,48 @@
# This file was auto-generated by Fern from our API Definition.
import datetime as dt
+from email.utils import parsedate_to_datetime
+from typing import Any
+
+import pydantic
+
+IS_PYDANTIC_V2 = pydantic.VERSION.startswith("2.")
+
+
+def parse_rfc2822_datetime(v: Any) -> dt.datetime:
+ """
+ Parse an RFC 2822 datetime string (e.g., "Wed, 02 Oct 2002 13:00:00 GMT")
+ into a datetime object. If the value is already a datetime, return it as-is.
+ Falls back to ISO 8601 parsing if RFC 2822 parsing fails.
+ """
+ if isinstance(v, dt.datetime):
+ return v
+ if isinstance(v, str):
+ try:
+ return parsedate_to_datetime(v)
+ except Exception:
+ pass
+ # Fallback to ISO 8601 parsing
+ return dt.datetime.fromisoformat(v.replace("Z", "+00:00"))
+ raise ValueError(f"Expected str or datetime, got {type(v)}")
+
+
+class Rfc2822DateTime(dt.datetime):
+ """A datetime subclass that parses RFC 2822 date strings.
+
+ On Pydantic V1, uses __get_validators__ for pre-validation.
+ On Pydantic V2, uses __get_pydantic_core_schema__ for BeforeValidator-style parsing.
+ """
+
+ @classmethod
+ def __get_validators__(cls): # type: ignore[no-untyped-def]
+ yield parse_rfc2822_datetime
+
+ @classmethod
+ def __get_pydantic_core_schema__(cls, _source_type: Any, _handler: Any) -> Any: # type: ignore[override]
+ from pydantic_core import core_schema
+
+ return core_schema.no_info_before_validator_function(parse_rfc2822_datetime, core_schema.datetime_schema())
def serialize_datetime(v: dt.datetime) -> str:
diff --git a/common/generated/rest/core/force_multipart.py b/common/generated/rest/core/force_multipart.py
index ae24ccff..5440913f 100644
--- a/common/generated/rest/core/force_multipart.py
+++ b/common/generated/rest/core/force_multipart.py
@@ -1,7 +1,9 @@
# This file was auto-generated by Fern from our API Definition.
+from typing import Any, Dict
-class ForceMultipartDict(dict):
+
+class ForceMultipartDict(Dict[str, Any]):
"""
A dictionary subclass that always evaluates to True in boolean contexts.
@@ -9,7 +11,7 @@ class ForceMultipartDict(dict):
the dictionary is empty, which would normally evaluate to False.
"""
- def __bool__(self):
+ def __bool__(self) -> bool:
return True
diff --git a/common/generated/rest/core/http_client.py b/common/generated/rest/core/http_client.py
index e4173f99..3e5a7865 100644
--- a/common/generated/rest/core/http_client.py
+++ b/common/generated/rest/core/http_client.py
@@ -3,9 +3,9 @@
import asyncio
import email.utils
import re
+import socket
import time
import typing
-import urllib.parse
from contextlib import asynccontextmanager, contextmanager
from random import random
@@ -13,14 +13,48 @@
from .file import File, convert_file_dict_to_httpx_tuples
from .force_multipart import FORCE_MULTIPART
from .jsonable_encoder import jsonable_encoder
+from .logging import LogConfig, Logger, create_logger
from .query_encoder import encode_query
-from .remove_none_from_dict import remove_none_from_dict
+from .remove_none_from_dict import remove_none_from_dict as remove_none_from_dict
from .request_options import RequestOptions
from httpx._types import RequestFiles
-INITIAL_RETRY_DELAY_SECONDS = 0.5
-MAX_RETRY_DELAY_SECONDS = 10
-MAX_RETRY_DELAY_SECONDS_FROM_HEADER = 30
+INITIAL_RETRY_DELAY_SECONDS = 1.0
+MAX_RETRY_DELAY_SECONDS = 60.0
+JITTER_FACTOR = 0.2 # 20% random jitter
+
+
+def get_keepalive_socket_options(
+ idle: int = 60,
+ intvl: int = 30,
+ cnt: int = 5,
+) -> typing.List[typing.Tuple[int, int, int]]:
+ """
+ Build TCP keepalive socket options for the current platform.
+
+ Keepalive probes keep otherwise-idle connections alive so that long,
+ non-streaming requests survive idle-connection reaping by a firewall,
+ load balancer, or NAT. The available socket constants are OS-dependent,
+ so each option is guarded and only emitted when the platform defines it:
+
+ - ``SO_KEEPALIVE`` is portable (Linux/macOS/Windows).
+ - The idle-before-first-probe knob is ``TCP_KEEPIDLE`` on Linux and modern
+ Windows, but ``TCP_KEEPALIVE`` on macOS.
+ - ``TCP_KEEPINTVL`` / ``TCP_KEEPCNT`` exist on Linux/macOS/modern Windows.
+
+ Passing these tuples to ``httpx.HTTPTransport(socket_options=...)`` /
+ ``httpx.AsyncHTTPTransport(socket_options=...)`` applies them to every
+ connection the transport opens.
+ """
+ opts: typing.List[typing.Tuple[int, int, int]] = [(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)]
+ idle_const = getattr(socket, "TCP_KEEPIDLE", None) or getattr(socket, "TCP_KEEPALIVE", None)
+ if idle_const:
+ opts.append((socket.IPPROTO_TCP, idle_const, idle))
+ if hasattr(socket, "TCP_KEEPINTVL"):
+ opts.append((socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, intvl))
+ if hasattr(socket, "TCP_KEEPCNT"):
+ opts.append((socket.IPPROTO_TCP, socket.TCP_KEEPCNT, cnt))
+ return opts
def _parse_retry_after(response_headers: httpx.Headers) -> typing.Optional[float]:
@@ -64,6 +98,38 @@ def _parse_retry_after(response_headers: httpx.Headers) -> typing.Optional[float
return seconds
+def _add_positive_jitter(delay: float) -> float:
+ """Add positive jitter (0-20%) to prevent thundering herd."""
+ jitter_multiplier = 1 + random() * JITTER_FACTOR
+ return delay * jitter_multiplier
+
+
+def _add_symmetric_jitter(delay: float) -> float:
+ """Add symmetric jitter (±10%) for exponential backoff."""
+ jitter_multiplier = 1 + (random() - 0.5) * JITTER_FACTOR
+ return delay * jitter_multiplier
+
+
+def _parse_x_ratelimit_reset(response_headers: httpx.Headers) -> typing.Optional[float]:
+ """
+ Parse the X-RateLimit-Reset header (Unix timestamp in seconds).
+ Returns seconds to wait, or None if header is missing/invalid.
+ """
+ reset_time_str = response_headers.get("x-ratelimit-reset")
+ if reset_time_str is None:
+ return None
+
+ try:
+ reset_time = int(reset_time_str)
+ delay = reset_time - time.time()
+ if delay > 0:
+ return delay
+ except (ValueError, TypeError):
+ pass
+
+ return None
+
+
def _retry_timeout(response: httpx.Response, retries: int) -> float:
"""
Determine the amount of time to wait before retrying a request.
@@ -71,22 +137,94 @@ def _retry_timeout(response: httpx.Response, retries: int) -> float:
with a jitter to determine the number of seconds to wait.
"""
- # If the API asks us to wait a certain amount of time (and it's a reasonable amount), just do what it says.
+ # 1. Check Retry-After header first
retry_after = _parse_retry_after(response.headers)
- if retry_after is not None and retry_after <= MAX_RETRY_DELAY_SECONDS_FROM_HEADER:
- return retry_after
+ if retry_after is not None and retry_after > 0:
+ return min(retry_after, MAX_RETRY_DELAY_SECONDS)
+
+ # 2. Check X-RateLimit-Reset header (with positive jitter)
+ ratelimit_reset = _parse_x_ratelimit_reset(response.headers)
+ if ratelimit_reset is not None:
+ return _add_positive_jitter(min(ratelimit_reset, MAX_RETRY_DELAY_SECONDS))
- # Apply exponential backoff, capped at MAX_RETRY_DELAY_SECONDS.
- retry_delay = min(INITIAL_RETRY_DELAY_SECONDS * pow(2.0, retries), MAX_RETRY_DELAY_SECONDS)
+ # 3. Fall back to exponential backoff (with symmetric jitter)
+ backoff = min(INITIAL_RETRY_DELAY_SECONDS * pow(2.0, retries), MAX_RETRY_DELAY_SECONDS)
+ return _add_symmetric_jitter(backoff)
- # Add a randomness / jitter to the retry delay to avoid overwhelming the server with retries.
- timeout = retry_delay * (1 - 0.25 * random())
- return timeout if timeout >= 0 else 0
+
+def _retry_timeout_from_retries(retries: int) -> float:
+ """Determine retry timeout using exponential backoff when no response is available."""
+ backoff = min(INITIAL_RETRY_DELAY_SECONDS * pow(2.0, retries), MAX_RETRY_DELAY_SECONDS)
+ return _add_symmetric_jitter(backoff)
def _should_retry(response: httpx.Response) -> bool:
- retryable_400s = [429, 408, 409]
- return response.status_code >= 500 or response.status_code in retryable_400s
+ return response.status_code >= 500 or response.status_code in [429, 408, 409]
+
+
+_SENSITIVE_HEADERS = frozenset(
+ {
+ "authorization",
+ "www-authenticate",
+ "x-api-key",
+ "api-key",
+ "apikey",
+ "x-api-token",
+ "x-auth-token",
+ "auth-token",
+ "cookie",
+ "set-cookie",
+ "proxy-authorization",
+ "proxy-authenticate",
+ "x-csrf-token",
+ "x-xsrf-token",
+ "x-session-token",
+ "x-access-token",
+ }
+)
+
+
+def _redact_headers(headers: typing.Dict[str, str]) -> typing.Dict[str, str]:
+ return {k: ("[REDACTED]" if k.lower() in _SENSITIVE_HEADERS else v) for k, v in headers.items()}
+
+
+def _build_url(base_url: str, path: typing.Optional[str]) -> str:
+ """
+ Build a full URL by joining a base URL with a path.
+
+ This function correctly handles base URLs that contain path prefixes (e.g., tenant-based URLs)
+ by using string concatenation instead of urllib.parse.urljoin(), which would incorrectly
+ strip path components when the path starts with '/'.
+
+ Example:
+ >>> _build_url("https://cloud.example.com/org/tenant/api", "/users")
+ 'https://cloud.example.com/org/tenant/api/users'
+
+ Args:
+ base_url: The base URL, which may contain path prefixes.
+ path: The path to append. Can be None or empty string.
+
+ Returns:
+ The full URL with base_url and path properly joined.
+ """
+ if not path:
+ return base_url
+ return f"{base_url.rstrip('/')}/{path.lstrip('/')}"
+
+
+def _maybe_filter_none_from_multipart_data(
+ data: typing.Optional[typing.Any],
+ request_files: typing.Optional[RequestFiles],
+ force_multipart: typing.Optional[bool],
+) -> typing.Optional[typing.Any]:
+ """
+ Filter None values from data body for multipart/form requests.
+ This prevents httpx from converting None to empty strings in multipart encoding.
+ Only applies when files are present or force_multipart is True.
+ """
+ if data is not None and isinstance(data, typing.Mapping) and (request_files or force_multipart):
+ return remove_none_from_dict(data)
+ return data
def remove_omit_from_dict(
@@ -134,7 +272,16 @@ def get_request_body(
data: typing.Optional[typing.Any],
request_options: typing.Optional[RequestOptions],
omit: typing.Optional[typing.Any],
+ optional_body: bool = False,
) -> typing.Tuple[typing.Optional[typing.Any], typing.Optional[typing.Any]]:
+ # A whole body left at the sentinel was never passed by the caller, so it is absent
+ # rather than empty: the request carries no content and no `Content-Type`.
+ if omit is not None:
+ if json is omit:
+ json = None
+ if data is omit:
+ data = None
+
json_body = None
data_body = None
if data is not None:
@@ -143,8 +290,41 @@ def get_request_body(
# If both data and json are None, we send json data in the event extra properties are specified
json_body = maybe_filter_request_body(json, request_options, omit)
- # If you have an empty JSON body, you should just send None
- return (json_body if json_body != {} else None), data_body if data_body != {} else None
+ has_additional_body_parameters = bool(
+ request_options is not None and request_options.get("additional_body_parameters")
+ )
+
+ # Only collapse empty dict to None when the body was not explicitly provided
+ # and there are no additional body parameters. This preserves explicit empty
+ # bodies (e.g., when an endpoint has a request body type but all fields are optional).
+ # `optional_body` marks an endpoint whose body the API does not require, where a body
+ # that ends up empty means the caller passed none of its properties, so the request is
+ # sent with no content and no `Content-Type`.
+ if json_body == {} and (json is None or optional_body) and not has_additional_body_parameters:
+ json_body = None
+ if data_body == {} and (data is None or optional_body) and not has_additional_body_parameters:
+ data_body = None
+
+ return json_body, data_body
+
+
+def drop_content_type_without_body(
+ headers: typing.Dict[str, typing.Any],
+ *,
+ json_body: typing.Optional[typing.Any],
+ data_body: typing.Optional[typing.Any],
+ optional_body: bool,
+) -> typing.Dict[str, typing.Any]:
+ """Strip ``Content-Type`` from a request that carries no body.
+
+ ``get_request_body`` drops the body of an ``optional_body`` endpoint when the caller
+ supplied none of it, but the endpoint still passes the content type it would have used.
+ A request that sends nothing must not advertise a media type, so a server that branches
+ on the header sees a bodyless call for what it is.
+ """
+ if not optional_body or json_body is not None or data_body is not None:
+ return headers
+ return {key: value for key, value in headers.items() if key.lower() != "content-type"}
class HttpClient:
@@ -155,11 +335,15 @@ def __init__(
base_timeout: typing.Callable[[], typing.Optional[float]],
base_headers: typing.Callable[[], typing.Dict[str, str]],
base_url: typing.Optional[typing.Callable[[], str]] = None,
+ base_max_retries: int = 2,
+ logging_config: typing.Optional[typing.Union[LogConfig, Logger]] = None,
):
self.base_url = base_url
self.base_timeout = base_timeout
self.base_headers = base_headers
+ self.base_max_retries = base_max_retries
self.httpx_client = httpx_client
+ self.logger = create_logger(logging_config)
def get_base_url(self, maybe_base_url: typing.Optional[str]) -> str:
base_url = maybe_base_url
@@ -188,18 +372,24 @@ def request(
] = None,
headers: typing.Optional[typing.Dict[str, typing.Any]] = None,
request_options: typing.Optional[RequestOptions] = None,
- retries: int = 2,
+ retries: int = 0,
omit: typing.Optional[typing.Any] = None,
+ optional_body: bool = False,
force_multipart: typing.Optional[bool] = None,
) -> httpx.Response:
base_url = self.get_base_url(base_url)
- timeout = (
- request_options.get("timeout_in_seconds")
+ _timeout = (
+ request_options.get("timeout")
+ if request_options is not None and request_options.get("timeout") is not None
+ else request_options.get("timeout_in_seconds")
if request_options is not None and request_options.get("timeout_in_seconds") is not None
else self.base_timeout()
)
+ timeout = _timeout if _timeout is not None else httpx.USE_CLIENT_DEFAULT
- json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit)
+ json_body, data_body = get_request_body(
+ json=json, data=data, request_options=request_options, omit=omit, optional_body=optional_body
+ )
request_files: typing.Optional[RequestFiles] = (
convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit))
@@ -210,45 +400,91 @@ def request(
if (request_files is None or len(request_files) == 0) and force_multipart:
request_files = FORCE_MULTIPART
- response = self.httpx_client.request(
- method=method,
- url=urllib.parse.urljoin(f"{base_url}/", path),
- headers=jsonable_encoder(
+ data_body = _maybe_filter_none_from_multipart_data(data_body, request_files, force_multipart)
+
+ # Compute encoded params separately to avoid passing empty list to httpx
+ # (httpx strips existing query params from URL when params=[] is passed)
+ _encoded_params = encode_query(
+ jsonable_encoder(
remove_none_from_dict(
- {
- **self.base_headers(),
- **(headers if headers is not None else {}),
- **(request_options.get("additional_headers", {}) or {} if request_options is not None else {}),
- }
- )
- ),
- params=encode_query(
- jsonable_encoder(
- remove_none_from_dict(
- remove_omit_from_dict(
- {
- **(params if params is not None else {}),
- **(
- request_options.get("additional_query_parameters", {}) or {}
- if request_options is not None
- else {}
- ),
- },
- omit,
- )
+ remove_omit_from_dict(
+ {
+ **(params if params is not None else {}),
+ **(
+ request_options.get("additional_query_parameters", {}) or {}
+ if request_options is not None
+ else {}
+ ),
+ },
+ omit,
)
)
- ),
- json=json_body,
- data=data_body,
- content=content,
- files=request_files,
- timeout=timeout,
+ )
+ )
+
+ _request_url = _build_url(base_url, path)
+ _request_headers = jsonable_encoder(
+ remove_none_from_dict(
+ {
+ **self.base_headers(),
+ **(headers if headers is not None else {}),
+ **(request_options.get("additional_headers", {}) or {} if request_options is not None else {}),
+ }
+ )
+ )
+ _request_headers = drop_content_type_without_body(
+ _request_headers, json_body=json_body, data_body=data_body, optional_body=optional_body
+ )
+
+ if self.logger.is_debug():
+ self.logger.debug(
+ "Making HTTP request",
+ method=method,
+ url=_request_url,
+ headers=_redact_headers(_request_headers),
+ has_body=json_body is not None or data_body is not None,
+ )
+
+ max_retries: int = (
+ request_options.get("max_retries", self.base_max_retries)
+ if request_options is not None
+ else self.base_max_retries
)
- max_retries: int = request_options.get("max_retries", 0) if request_options is not None else 0
+ try:
+ response = self.httpx_client.request(
+ method=method,
+ url=_request_url,
+ headers=_request_headers,
+ params=_encoded_params if _encoded_params else None,
+ json=json_body,
+ data=data_body,
+ content=content,
+ files=request_files,
+ timeout=timeout,
+ )
+ except (httpx.ConnectError, httpx.RemoteProtocolError):
+ if retries < max_retries:
+ time.sleep(_retry_timeout_from_retries(retries=retries))
+ return self.request(
+ path=path,
+ method=method,
+ base_url=base_url,
+ params=params,
+ json=json,
+ data=data,
+ content=content,
+ files=files,
+ headers=headers,
+ request_options=request_options,
+ retries=retries + 1,
+ omit=omit,
+ force_multipart=force_multipart,
+ )
+ raise
+
if _should_retry(response=response):
- if max_retries > retries:
+ if retries < max_retries:
time.sleep(_retry_timeout(response=response, retries=retries))
return self.request(
path=path,
@@ -256,12 +492,32 @@ def request(
base_url=base_url,
params=params,
json=json,
+ data=data,
content=content,
files=files,
headers=headers,
request_options=request_options,
retries=retries + 1,
omit=omit,
+ force_multipart=force_multipart,
+ )
+
+ if self.logger.is_debug():
+ if 200 <= response.status_code < 400:
+ self.logger.debug(
+ "HTTP request succeeded",
+ method=method,
+ url=_request_url,
+ status_code=response.status_code,
+ )
+
+ if self.logger.is_error():
+ if response.status_code >= 400:
+ self.logger.error(
+ "HTTP request failed with error status",
+ method=method,
+ url=_request_url,
+ status_code=response.status_code,
)
return response
@@ -285,16 +541,20 @@ def stream(
] = None,
headers: typing.Optional[typing.Dict[str, typing.Any]] = None,
request_options: typing.Optional[RequestOptions] = None,
- retries: int = 2,
+ retries: int = 0,
omit: typing.Optional[typing.Any] = None,
+ optional_body: bool = False,
force_multipart: typing.Optional[bool] = None,
) -> typing.Iterator[httpx.Response]:
base_url = self.get_base_url(base_url)
- timeout = (
- request_options.get("timeout_in_seconds")
+ _timeout = (
+ request_options.get("timeout")
+ if request_options is not None and request_options.get("timeout") is not None
+ else request_options.get("timeout_in_seconds")
if request_options is not None and request_options.get("timeout_in_seconds") is not None
else self.base_timeout()
)
+ timeout = _timeout if _timeout is not None else httpx.USE_CLIENT_DEFAULT
request_files: typing.Optional[RequestFiles] = (
convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit))
@@ -305,37 +565,59 @@ def stream(
if (request_files is None or len(request_files) == 0) and force_multipart:
request_files = FORCE_MULTIPART
- json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit)
+ json_body, data_body = get_request_body(
+ json=json, data=data, request_options=request_options, omit=omit, optional_body=optional_body
+ )
+
+ data_body = _maybe_filter_none_from_multipart_data(data_body, request_files, force_multipart)
- with self.httpx_client.stream(
- method=method,
- url=urllib.parse.urljoin(f"{base_url}/", path),
- headers=jsonable_encoder(
+ # Compute encoded params separately to avoid passing empty list to httpx
+ # (httpx strips existing query params from URL when params=[] is passed)
+ _encoded_params = encode_query(
+ jsonable_encoder(
remove_none_from_dict(
- {
- **self.base_headers(),
- **(headers if headers is not None else {}),
- **(request_options.get("additional_headers", {}) if request_options is not None else {}),
- }
- )
- ),
- params=encode_query(
- jsonable_encoder(
- remove_none_from_dict(
- remove_omit_from_dict(
- {
- **(params if params is not None else {}),
- **(
- request_options.get("additional_query_parameters", {})
- if request_options is not None
- else {}
- ),
- },
- omit,
- )
+ remove_omit_from_dict(
+ {
+ **(params if params is not None else {}),
+ **(
+ request_options.get("additional_query_parameters", {})
+ if request_options is not None
+ else {}
+ ),
+ },
+ omit,
)
)
- ),
+ )
+ )
+
+ _request_url = _build_url(base_url, path)
+ _request_headers = jsonable_encoder(
+ remove_none_from_dict(
+ {
+ **self.base_headers(),
+ **(headers if headers is not None else {}),
+ **(request_options.get("additional_headers", {}) if request_options is not None else {}),
+ }
+ )
+ )
+ _request_headers = drop_content_type_without_body(
+ _request_headers, json_body=json_body, data_body=data_body, optional_body=optional_body
+ )
+
+ if self.logger.is_debug():
+ self.logger.debug(
+ "Making streaming HTTP request",
+ method=method,
+ url=_request_url,
+ headers=_redact_headers(_request_headers),
+ )
+
+ with self.httpx_client.stream(
+ method=method,
+ url=_request_url,
+ headers=_request_headers,
+ params=_encoded_params if _encoded_params else None,
json=json_body,
data=data_body,
content=content,
@@ -353,11 +635,22 @@ def __init__(
base_timeout: typing.Callable[[], typing.Optional[float]],
base_headers: typing.Callable[[], typing.Dict[str, str]],
base_url: typing.Optional[typing.Callable[[], str]] = None,
+ base_max_retries: int = 2,
+ async_base_headers: typing.Optional[typing.Callable[[], typing.Awaitable[typing.Dict[str, str]]]] = None,
+ logging_config: typing.Optional[typing.Union[LogConfig, Logger]] = None,
):
self.base_url = base_url
self.base_timeout = base_timeout
self.base_headers = base_headers
+ self.base_max_retries = base_max_retries
+ self.async_base_headers = async_base_headers
self.httpx_client = httpx_client
+ self.logger = create_logger(logging_config)
+
+ async def _get_headers(self) -> typing.Dict[str, str]:
+ if self.async_base_headers is not None:
+ return await self.async_base_headers()
+ return self.base_headers()
def get_base_url(self, maybe_base_url: typing.Optional[str]) -> str:
base_url = maybe_base_url
@@ -386,16 +679,20 @@ async def request(
] = None,
headers: typing.Optional[typing.Dict[str, typing.Any]] = None,
request_options: typing.Optional[RequestOptions] = None,
- retries: int = 2,
+ retries: int = 0,
omit: typing.Optional[typing.Any] = None,
+ optional_body: bool = False,
force_multipart: typing.Optional[bool] = None,
) -> httpx.Response:
base_url = self.get_base_url(base_url)
- timeout = (
- request_options.get("timeout_in_seconds")
+ _timeout = (
+ request_options.get("timeout")
+ if request_options is not None and request_options.get("timeout") is not None
+ else request_options.get("timeout_in_seconds")
if request_options is not None and request_options.get("timeout_in_seconds") is not None
else self.base_timeout()
)
+ timeout = _timeout if _timeout is not None else httpx.USE_CLIENT_DEFAULT
request_files: typing.Optional[RequestFiles] = (
convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit))
@@ -406,48 +703,98 @@ async def request(
if (request_files is None or len(request_files) == 0) and force_multipart:
request_files = FORCE_MULTIPART
- json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit)
+ json_body, data_body = get_request_body(
+ json=json, data=data, request_options=request_options, omit=omit, optional_body=optional_body
+ )
- # Add the input to each of these and do None-safety checks
- response = await self.httpx_client.request(
- method=method,
- url=urllib.parse.urljoin(f"{base_url}/", path),
- headers=jsonable_encoder(
+ data_body = _maybe_filter_none_from_multipart_data(data_body, request_files, force_multipart)
+
+ # Get headers (supports async token providers)
+ _headers = await self._get_headers()
+
+ # Compute encoded params separately to avoid passing empty list to httpx
+ # (httpx strips existing query params from URL when params=[] is passed)
+ _encoded_params = encode_query(
+ jsonable_encoder(
remove_none_from_dict(
- {
- **self.base_headers(),
- **(headers if headers is not None else {}),
- **(request_options.get("additional_headers", {}) or {} if request_options is not None else {}),
- }
- )
- ),
- params=encode_query(
- jsonable_encoder(
- remove_none_from_dict(
- remove_omit_from_dict(
- {
- **(params if params is not None else {}),
- **(
- request_options.get("additional_query_parameters", {}) or {}
- if request_options is not None
- else {}
- ),
- },
- omit,
- )
+ remove_omit_from_dict(
+ {
+ **(params if params is not None else {}),
+ **(
+ request_options.get("additional_query_parameters", {}) or {}
+ if request_options is not None
+ else {}
+ ),
+ },
+ omit,
)
)
- ),
- json=json_body,
- data=data_body,
- content=content,
- files=request_files,
- timeout=timeout,
+ )
+ )
+
+ _request_url = _build_url(base_url, path)
+ _request_headers = jsonable_encoder(
+ remove_none_from_dict(
+ {
+ **_headers,
+ **(headers if headers is not None else {}),
+ **(request_options.get("additional_headers", {}) or {} if request_options is not None else {}),
+ }
+ )
+ )
+ _request_headers = drop_content_type_without_body(
+ _request_headers, json_body=json_body, data_body=data_body, optional_body=optional_body
+ )
+
+ if self.logger.is_debug():
+ self.logger.debug(
+ "Making HTTP request",
+ method=method,
+ url=_request_url,
+ headers=_redact_headers(_request_headers),
+ has_body=json_body is not None or data_body is not None,
+ )
+
+ max_retries: int = (
+ request_options.get("max_retries", self.base_max_retries)
+ if request_options is not None
+ else self.base_max_retries
)
- max_retries: int = request_options.get("max_retries", 0) if request_options is not None else 0
+ try:
+ response = await self.httpx_client.request(
+ method=method,
+ url=_request_url,
+ headers=_request_headers,
+ params=_encoded_params if _encoded_params else None,
+ json=json_body,
+ data=data_body,
+ content=content,
+ files=request_files,
+ timeout=timeout,
+ )
+ except (httpx.ConnectError, httpx.RemoteProtocolError):
+ if retries < max_retries:
+ await asyncio.sleep(_retry_timeout_from_retries(retries=retries))
+ return await self.request(
+ path=path,
+ method=method,
+ base_url=base_url,
+ params=params,
+ json=json,
+ data=data,
+ content=content,
+ files=files,
+ headers=headers,
+ request_options=request_options,
+ retries=retries + 1,
+ omit=omit,
+ force_multipart=force_multipart,
+ )
+ raise
+
if _should_retry(response=response):
- if max_retries > retries:
+ if retries < max_retries:
await asyncio.sleep(_retry_timeout(response=response, retries=retries))
return await self.request(
path=path,
@@ -455,13 +802,34 @@ async def request(
base_url=base_url,
params=params,
json=json,
+ data=data,
content=content,
files=files,
headers=headers,
request_options=request_options,
retries=retries + 1,
omit=omit,
+ force_multipart=force_multipart,
+ )
+
+ if self.logger.is_debug():
+ if 200 <= response.status_code < 400:
+ self.logger.debug(
+ "HTTP request succeeded",
+ method=method,
+ url=_request_url,
+ status_code=response.status_code,
+ )
+
+ if self.logger.is_error():
+ if response.status_code >= 400:
+ self.logger.error(
+ "HTTP request failed with error status",
+ method=method,
+ url=_request_url,
+ status_code=response.status_code,
)
+
return response
@asynccontextmanager
@@ -483,16 +851,20 @@ async def stream(
] = None,
headers: typing.Optional[typing.Dict[str, typing.Any]] = None,
request_options: typing.Optional[RequestOptions] = None,
- retries: int = 2,
+ retries: int = 0,
omit: typing.Optional[typing.Any] = None,
+ optional_body: bool = False,
force_multipart: typing.Optional[bool] = None,
) -> typing.AsyncIterator[httpx.Response]:
base_url = self.get_base_url(base_url)
- timeout = (
- request_options.get("timeout_in_seconds")
+ _timeout = (
+ request_options.get("timeout")
+ if request_options is not None and request_options.get("timeout") is not None
+ else request_options.get("timeout_in_seconds")
if request_options is not None and request_options.get("timeout_in_seconds") is not None
else self.base_timeout()
)
+ timeout = _timeout if _timeout is not None else httpx.USE_CLIENT_DEFAULT
request_files: typing.Optional[RequestFiles] = (
convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit))
@@ -503,37 +875,62 @@ async def stream(
if (request_files is None or len(request_files) == 0) and force_multipart:
request_files = FORCE_MULTIPART
- json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit)
+ json_body, data_body = get_request_body(
+ json=json, data=data, request_options=request_options, omit=omit, optional_body=optional_body
+ )
- async with self.httpx_client.stream(
- method=method,
- url=urllib.parse.urljoin(f"{base_url}/", path),
- headers=jsonable_encoder(
+ data_body = _maybe_filter_none_from_multipart_data(data_body, request_files, force_multipart)
+
+ # Get headers (supports async token providers)
+ _headers = await self._get_headers()
+
+ # Compute encoded params separately to avoid passing empty list to httpx
+ # (httpx strips existing query params from URL when params=[] is passed)
+ _encoded_params = encode_query(
+ jsonable_encoder(
remove_none_from_dict(
- {
- **self.base_headers(),
- **(headers if headers is not None else {}),
- **(request_options.get("additional_headers", {}) if request_options is not None else {}),
- }
- )
- ),
- params=encode_query(
- jsonable_encoder(
- remove_none_from_dict(
- remove_omit_from_dict(
- {
- **(params if params is not None else {}),
- **(
- request_options.get("additional_query_parameters", {})
- if request_options is not None
- else {}
- ),
- },
- omit=omit,
- )
+ remove_omit_from_dict(
+ {
+ **(params if params is not None else {}),
+ **(
+ request_options.get("additional_query_parameters", {})
+ if request_options is not None
+ else {}
+ ),
+ },
+ omit=omit,
)
)
- ),
+ )
+ )
+
+ _request_url = _build_url(base_url, path)
+ _request_headers = jsonable_encoder(
+ remove_none_from_dict(
+ {
+ **_headers,
+ **(headers if headers is not None else {}),
+ **(request_options.get("additional_headers", {}) if request_options is not None else {}),
+ }
+ )
+ )
+ _request_headers = drop_content_type_without_body(
+ _request_headers, json_body=json_body, data_body=data_body, optional_body=optional_body
+ )
+
+ if self.logger.is_debug():
+ self.logger.debug(
+ "Making streaming HTTP request",
+ method=method,
+ url=_request_url,
+ headers=_redact_headers(_request_headers),
+ )
+
+ async with self.httpx_client.stream(
+ method=method,
+ url=_request_url,
+ headers=_request_headers,
+ params=_encoded_params if _encoded_params else None,
json=json_body,
data=data_body,
content=content,
diff --git a/common/generated/rest/core/http_response.py b/common/generated/rest/core/http_response.py
index 48a1798a..9aa1e188 100644
--- a/common/generated/rest/core/http_response.py
+++ b/common/generated/rest/core/http_response.py
@@ -4,12 +4,12 @@
import httpx
+# Generic to represent the underlying type of the data wrapped by the HTTP response.
T = TypeVar("T")
-"""Generic to represent the underlying type of the data wrapped by the HTTP response."""
class BaseHttpResponse:
- """Minimalist HTTP response wrapper that exposes response headers."""
+ """Minimalist HTTP response wrapper that exposes response headers and status code."""
_response: httpx.Response
@@ -20,6 +20,14 @@ def __init__(self, response: httpx.Response):
def headers(self) -> Dict[str, str]:
return dict(self._response.headers)
+ @property
+ def status_code(self) -> int:
+ return self._response.status_code
+
+ @property
+ def response(self) -> httpx.Response:
+ return self._response
+
class HttpResponse(Generic[T], BaseHttpResponse):
"""HTTP response wrapper that exposes response headers and data."""
diff --git a/common/generated/rest/core/http_sse/__init__.py b/common/generated/rest/core/http_sse/__init__.py
new file mode 100644
index 00000000..730e5a33
--- /dev/null
+++ b/common/generated/rest/core/http_sse/__init__.py
@@ -0,0 +1,42 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from ._api import EventSource, aconnect_sse, connect_sse
+ from ._exceptions import SSEError
+ from ._models import ServerSentEvent
+_dynamic_imports: typing.Dict[str, str] = {
+ "EventSource": "._api",
+ "SSEError": "._exceptions",
+ "ServerSentEvent": "._models",
+ "aconnect_sse": "._api",
+ "connect_sse": "._api",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = ["EventSource", "SSEError", "ServerSentEvent", "aconnect_sse", "connect_sse"]
diff --git a/common/generated/rest/core/http_sse/_api.py b/common/generated/rest/core/http_sse/_api.py
new file mode 100644
index 00000000..9ca5602c
--- /dev/null
+++ b/common/generated/rest/core/http_sse/_api.py
@@ -0,0 +1,455 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import codecs
+import re
+import time
+from contextlib import asynccontextmanager, contextmanager
+from typing import (
+ Any,
+ AsyncContextManager,
+ AsyncGenerator,
+ AsyncIterator,
+ Callable,
+ ContextManager,
+ Iterator,
+ Optional,
+)
+
+import anyio
+import httpx
+from ._decoders import SSEDecoder
+from ._exceptions import SSEError
+from ._models import ServerSentEvent
+
+MAX_LINE_SIZE: int = 1_048_576 # 1 MiB
+
+# Reconnection defaults, mirroring the TypeScript SDK's Stream implementation.
+DEFAULT_MAX_RECONNECTION_ATTEMPTS: int = 5
+DEFAULT_RECONNECT_DELAY_MS: int = 1_000
+MAX_RECONNECT_DELAY_MS: int = 30_000
+
+
+# A reconnect callback re-issues the original request (with a ``Last-Event-ID``
+# header set to the supplied event id) and returns a *context manager* yielding
+# a fresh streaming ``httpx.Response``. Sync clients supply a sync context
+# manager; async clients supply an async one.
+class EventSource:
+ def __init__(
+ self,
+ response: httpx.Response,
+ *,
+ resumable: bool = False,
+ stream_reconnection_enabled: bool = True,
+ max_stream_reconnection_attempts: Optional[int] = None,
+ stream_terminator: Optional[str] = None,
+ reconnect: Optional[Callable[[str], Any]] = None,
+ ) -> None:
+ self._response = response
+ self._resumable = resumable
+ self._stream_reconnection_enabled = stream_reconnection_enabled
+ self._max_stream_reconnection_attempts = max_stream_reconnection_attempts
+ self._stream_terminator = stream_terminator
+ self._reconnect = reconnect
+
+ @staticmethod
+ def _is_event_stream(response: httpx.Response) -> bool:
+ content_type = response.headers.get("content-type", "").partition(";")[0]
+ return "text/event-stream" in content_type
+
+ def _check_content_type(self) -> None:
+ if not self._is_event_stream(self._response):
+ content_type = self._response.headers.get("content-type", "").partition(";")[0]
+ raise SSEError(
+ f"Expected response header Content-Type to contain 'text/event-stream', got {content_type!r}"
+ )
+
+ def _is_reconnect_response_usable(self, response: httpx.Response) -> bool:
+ """Whether a reconnected response can be resumed as an SSE stream.
+
+ ``httpx.stream`` does not raise on non-success status, so a resume that
+ returns an error page (e.g. ``200 text/html`` or a ``500`` body) would
+ otherwise be parsed as SSE and yield garbage/zero events. Such a
+ response is treated as a failed attempt (back off and retry) instead.
+ """
+ return response.status_code < 400 and self._is_event_stream(response)
+
+ def _get_charset(self, response: Optional[httpx.Response] = None) -> str:
+ """Extract charset from Content-Type header, fallback to UTF-8."""
+ resolved = response if response is not None else self._response
+ content_type = resolved.headers.get("content-type", "")
+
+ # Parse charset parameter using regex
+ charset_match = re.search(r"charset=([^;\s]+)", content_type, re.IGNORECASE)
+ if charset_match:
+ charset = charset_match.group(1).strip("\"'")
+ # Validate that it's a known encoding
+ try:
+ # Test if the charset is valid by trying to encode/decode
+ "test".encode(charset).decode(charset)
+ return charset
+ except (LookupError, UnicodeError):
+ # If charset is invalid, fall back to UTF-8
+ pass
+
+ # Default to UTF-8 if no charset specified or invalid charset
+ return "utf-8"
+
+ @property
+ def response(self) -> httpx.Response:
+ return self._response
+
+ @staticmethod
+ def _normalize_sse_line_endings(buf: str) -> str:
+ """Normalize line endings per the SSE spec (\\r\\n → \\n, bare \\r → \\n).
+
+ A trailing \\r is preserved because it may pair with a leading \\n in
+ the next chunk to form a single \\r\\n terminator.
+ """
+ buf = buf.replace("\r\n", "\n")
+ if buf.endswith("\r"):
+ return buf[:-1].replace("\r", "\n") + "\r"
+ return buf.replace("\r", "\n")
+
+ def _new_text_decoder(self, response: Optional[httpx.Response] = None) -> "codecs.IncrementalDecoder":
+ return codecs.getincrementaldecoder(self._get_charset(response))(errors="replace")
+
+ def _reconnect_applicable(self) -> bool:
+ """Whether reconnection is configured for this stream at all.
+
+ This is the terminator-gating half of the reconnect decision, kept
+ separate from :meth:`_should_reconnect` (which additionally requires a
+ last *dispatched* id and an unexhausted attempt budget). The split lets
+ a mid-stream transport error terminate consistently:
+ - a stream that can never reconnect (non-resumable, no terminator,
+ disabled, or no callback) must re-raise the error to the caller, so a
+ truncated stream is not mistaken for a clean completion;
+ - a resumable stream that has merely run out of attempts (or has no id
+ to resume from) ends cleanly — the same way an exhausted empty/error
+ -body resume already does, matching the TypeScript ``return``.
+ """
+ return (
+ self._resumable
+ and self._stream_terminator is not None
+ and self._stream_reconnection_enabled
+ and self._reconnect is not None
+ )
+
+ def _should_reconnect(self, last_dispatched_id: Optional[str], reconnect_attempts: int) -> bool:
+ """Decide whether a prematurely-ended stream should be reconnected.
+
+ Mirrors the TypeScript ``shouldReconnect`` gating:
+ - only resumable SSE endpoints with a configured terminator, reconnect
+ enabled, and a reconnect callback are eligible (see
+ :meth:`_reconnect_applicable`);
+ - a last *dispatched* event id must exist to resume from;
+ - the consecutive-failed-attempt cap must not be exceeded.
+ """
+ if not self._reconnect_applicable():
+ return False
+ if not last_dispatched_id:
+ return False
+ max_attempts = (
+ self._max_stream_reconnection_attempts
+ if self._max_stream_reconnection_attempts is not None
+ else DEFAULT_MAX_RECONNECTION_ATTEMPTS
+ )
+ if reconnect_attempts >= max_attempts:
+ return False
+ return True
+
+ def _reconnect_delay_seconds(self, last_retry: Optional[int]) -> float:
+ """Backoff before a reconnect.
+
+ Uses the server's most recent ``retry:`` directive (milliseconds) when
+ present, otherwise a default of ``DEFAULT_RECONNECT_DELAY_MS``, clamped
+ to ``MAX_RECONNECT_DELAY_MS``.
+ """
+ base_ms = last_retry if (last_retry is not None and last_retry > 0) else DEFAULT_RECONNECT_DELAY_MS
+ return min(base_ms, MAX_RECONNECT_DELAY_MS) / 1000.0
+
+ def _sleep_before_reconnect(self, last_retry: Optional[int]) -> None:
+ # ``time.sleep`` blocks the calling thread but remains interruptible by
+ # signals (e.g. ``KeyboardInterrupt``), which propagate out and abort
+ # the reconnect without issuing another request.
+ time.sleep(self._reconnect_delay_seconds(last_retry))
+
+ async def _asleep_before_reconnect(self, last_retry: Optional[int]) -> None:
+ # ``anyio.sleep`` is cancellation-aware: if the consumer cancels the task
+ # or closes the async generator mid-delay, this raises (and no further
+ # request is issued) instead of blocking for the whole interval.
+ await anyio.sleep(self._reconnect_delay_seconds(last_retry))
+
+ def _decode_response(
+ self,
+ response: httpx.Response,
+ decoder: SSEDecoder,
+ text_decoder: "codecs.IncrementalDecoder",
+ ) -> Iterator[ServerSentEvent]:
+ buf = ""
+ for chunk in response.iter_bytes():
+ buf += text_decoder.decode(chunk)
+ buf = self._normalize_sse_line_endings(buf)
+
+ while "\n" in buf:
+ line, buf = buf.split("\n", 1)
+ sse = decoder.decode(line)
+ if sse is not None:
+ yield sse
+
+ if len(buf) > MAX_LINE_SIZE:
+ raise SSEError(
+ f"SSE line exceeded maximum size of {MAX_LINE_SIZE} characters without encountering a newline"
+ )
+
+ yield from self._flush_decoder(buf, decoder, text_decoder)
+
+ async def _adecode_response(
+ self,
+ response: httpx.Response,
+ decoder: SSEDecoder,
+ text_decoder: "codecs.IncrementalDecoder",
+ ) -> AsyncGenerator[ServerSentEvent, None]:
+ buf = ""
+ async for chunk in response.aiter_bytes():
+ buf += text_decoder.decode(chunk)
+ buf = self._normalize_sse_line_endings(buf)
+
+ while "\n" in buf:
+ line, buf = buf.split("\n", 1)
+ sse = decoder.decode(line)
+ if sse is not None:
+ yield sse
+
+ if len(buf) > MAX_LINE_SIZE:
+ raise SSEError(
+ f"SSE line exceeded maximum size of {MAX_LINE_SIZE} characters without encountering a newline"
+ )
+
+ for sse in self._flush_decoder(buf, decoder, text_decoder):
+ yield sse
+
+ def _flush_decoder(
+ self,
+ buf: str,
+ decoder: SSEDecoder,
+ text_decoder: "codecs.IncrementalDecoder",
+ ) -> Iterator[ServerSentEvent]:
+ # Flush any remaining bytes from the incremental decoder
+ buf += text_decoder.decode(b"", final=True)
+ buf = buf.replace("\r\n", "\n").replace("\r", "\n")
+
+ if len(buf) > MAX_LINE_SIZE:
+ raise SSEError(
+ f"SSE line exceeded maximum size of {MAX_LINE_SIZE} characters without encountering a newline"
+ )
+
+ while "\n" in buf:
+ line, buf = buf.split("\n", 1)
+ sse = decoder.decode(line)
+ if sse is not None:
+ yield sse
+
+ if buf.strip():
+ sse = decoder.decode(buf)
+ if sse is not None:
+ yield sse
+
+ def iter_sse(self) -> Iterator[ServerSentEvent]:
+ self._check_content_type()
+ decoder = SSEDecoder()
+ text_decoder = self._new_text_decoder()
+
+ last_dispatched_id: Optional[str] = None
+ last_retry: Optional[int] = None
+ # Consecutive failed reconnection attempts. Reset to 0 whenever an event
+ # is successfully dispatched (reset-on-progress) — matching browser
+ # `EventSource` semantics: a server that emits >=1 event then drops on
+ # every connection can reconnect indefinitely.
+ reconnect_attempts = 0
+
+ # ``None`` means there is no live stream to read this iteration (e.g. a
+ # failed reconnect); the loop then re-evaluates the reconnect decision
+ # without re-reading an exhausted response.
+ response: Optional[httpx.Response] = self._response
+ # Context manager for a response we opened ourselves and must close.
+ # The initial response is owned by the caller, so it starts as None.
+ owned_cm: Optional[ContextManager[httpx.Response]] = None
+ try:
+ while True:
+ if response is not None:
+ events = self._decode_response(response, decoder, text_decoder)
+ while True:
+ try:
+ sse = next(events)
+ except StopIteration:
+ break
+ except SSEError:
+ # A protocol violation (e.g. an oversized line) is a
+ # genuine error, not a dropped connection; propagate it.
+ # Listed first because ``SSEError`` subclasses
+ # ``httpx.TransportError``.
+ raise
+ except httpx.TransportError:
+ # A transport error mid-stream (e.g. the server dropped
+ # the connection: ``ReadError``/``RemoteProtocolError``)
+ # is a premature end. Only swallow it when reconnection
+ # is configured for this stream; otherwise re-raise so a
+ # non-resumable stream still surfaces the error to the
+ # caller instead of looking like a clean completion.
+ # When reconnection is applicable but the attempt budget
+ # is exhausted, we ``break`` and end cleanly below — the
+ # same way an exhausted empty/error-body resume does, so
+ # give-up is consistent regardless of failure shape.
+ # ``next`` is used rather than ``for`` so this cannot
+ # swallow a ``GeneratorExit`` raised at a ``yield``.
+ if not self._reconnect_applicable():
+ raise
+ break
+ yield sse
+ if sse.id:
+ last_dispatched_id = sse.id
+ if sse.retry is not None:
+ last_retry = sse.retry
+ reconnect_attempts = 0
+
+ if not self._should_reconnect(last_dispatched_id, reconnect_attempts):
+ return
+ reconnect_attempts += 1
+
+ self._sleep_before_reconnect(last_retry)
+
+ # Close the previously-opened reconnect response before opening
+ # a new one so we never hold more than one extra connection.
+ if owned_cm is not None:
+ owned_cm.__exit__(None, None, None)
+ owned_cm = None
+
+ assert self._reconnect is not None # guaranteed by _should_reconnect
+ try:
+ cm: ContextManager[httpx.Response] = self._reconnect(last_dispatched_id or "")
+ new_response = cm.__enter__()
+ except Exception:
+ # A failed reconnect consumes an attempt; back off and retry.
+ response = None
+ continue
+ owned_cm = cm
+ if new_response is None or not self._is_reconnect_response_usable(new_response):
+ # Null/empty body or a non-SSE/error response (e.g. 204/304,
+ # a 500, or an HTML error page): treat as a failed attempt.
+ response = None
+ continue
+
+ response = new_response
+ # Drop any partial event left over from the dropped stream, but
+ # keep the last event id (per the SSE spec) and start a fresh
+ # incremental text decoder for the new connection.
+ decoder.reset_in_progress_event()
+ text_decoder = self._new_text_decoder(new_response)
+ finally:
+ if owned_cm is not None:
+ owned_cm.__exit__(None, None, None)
+
+ async def aiter_sse(self) -> AsyncGenerator[ServerSentEvent, None]:
+ self._check_content_type()
+ decoder = SSEDecoder()
+ text_decoder = self._new_text_decoder()
+
+ last_dispatched_id: Optional[str] = None
+ last_retry: Optional[int] = None
+ reconnect_attempts = 0
+
+ response: Optional[httpx.Response] = self._response
+ owned_cm: Optional[AsyncContextManager[httpx.Response]] = None
+ try:
+ while True:
+ if response is not None:
+ events = self._adecode_response(response, decoder, text_decoder)
+ while True:
+ try:
+ sse = await events.__anext__()
+ except StopAsyncIteration:
+ break
+ except SSEError:
+ # A protocol violation (e.g. an oversized line) is a
+ # genuine error, not a dropped connection; propagate it.
+ # Listed first because ``SSEError`` subclasses
+ # ``httpx.TransportError``.
+ raise
+ except httpx.TransportError:
+ # A transport error mid-stream (e.g. the server dropped
+ # the connection: ``ReadError``/``RemoteProtocolError``)
+ # is a premature end. Only swallow it when reconnection
+ # is configured for this stream; otherwise re-raise so a
+ # non-resumable stream still surfaces the error to the
+ # caller instead of looking like a clean completion.
+ # When reconnection is applicable but the attempt budget
+ # is exhausted, we ``break`` and end cleanly below — the
+ # same way an exhausted empty/error-body resume does, so
+ # give-up is consistent regardless of failure shape.
+ if not self._reconnect_applicable():
+ raise
+ break
+ yield sse
+ if sse.id:
+ last_dispatched_id = sse.id
+ if sse.retry is not None:
+ last_retry = sse.retry
+ reconnect_attempts = 0
+
+ if not self._should_reconnect(last_dispatched_id, reconnect_attempts):
+ return
+ reconnect_attempts += 1
+
+ await self._asleep_before_reconnect(last_retry)
+
+ if owned_cm is not None:
+ await owned_cm.__aexit__(None, None, None)
+ owned_cm = None
+
+ assert self._reconnect is not None # guaranteed by _should_reconnect
+ try:
+ cm: AsyncContextManager[httpx.Response] = self._reconnect(last_dispatched_id or "")
+ new_response = await cm.__aenter__()
+ except Exception:
+ response = None
+ continue
+ owned_cm = cm
+ if new_response is None or not self._is_reconnect_response_usable(new_response):
+ response = None
+ continue
+
+ response = new_response
+ decoder.reset_in_progress_event()
+ text_decoder = self._new_text_decoder(new_response)
+ finally:
+ if owned_cm is not None:
+ # Shield the close so a cancellation delivered while reading a
+ # reconnected response still fully tears the connection down
+ # instead of leaking it until the client is closed.
+ with anyio.CancelScope(shield=True):
+ await owned_cm.__aexit__(None, None, None)
+
+
+@contextmanager
+def connect_sse(client: httpx.Client, method: str, url: str, **kwargs: Any) -> Iterator[EventSource]:
+ headers = kwargs.pop("headers", {})
+ headers["Accept"] = "text/event-stream"
+ headers["Cache-Control"] = "no-store"
+
+ with client.stream(method, url, headers=headers, **kwargs) as response:
+ yield EventSource(response)
+
+
+@asynccontextmanager
+async def aconnect_sse(
+ client: httpx.AsyncClient,
+ method: str,
+ url: str,
+ **kwargs: Any,
+) -> AsyncIterator[EventSource]:
+ headers = kwargs.pop("headers", {})
+ headers["Accept"] = "text/event-stream"
+ headers["Cache-Control"] = "no-store"
+
+ async with client.stream(method, url, headers=headers, **kwargs) as response:
+ yield EventSource(response)
diff --git a/common/generated/rest/core/http_sse/_decoders.py b/common/generated/rest/core/http_sse/_decoders.py
new file mode 100644
index 00000000..1f6b35ec
--- /dev/null
+++ b/common/generated/rest/core/http_sse/_decoders.py
@@ -0,0 +1,74 @@
+# This file was auto-generated by Fern from our API Definition.
+
+from typing import List, Optional
+
+from ._models import ServerSentEvent
+
+
+class SSEDecoder:
+ def __init__(self) -> None:
+ self._event = ""
+ self._data: List[str] = []
+ self._last_event_id = ""
+ self._retry: Optional[int] = None
+
+ def reset_in_progress_event(self) -> None:
+ """Discard any partially-parsed (undispatched) event.
+
+ Used when a stream ends mid-event before reconnecting: the buffered
+ ``event``/``data``/``retry`` fields of the never-dispatched event must
+ be dropped so they do not corrupt the first event of the reconnected
+ stream. Per the SSE spec the last event id is *not* reset here — it
+ persists across connections.
+ """
+ self._event = ""
+ self._data = []
+ self._retry = None
+
+ def decode(self, line: str) -> Optional[ServerSentEvent]:
+ # See: https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation # noqa: E501
+
+ if not line:
+ if not self._event and not self._data and not self._last_event_id and self._retry is None:
+ return None
+
+ sse = ServerSentEvent(
+ event=self._event,
+ data="\n".join(self._data),
+ id=self._last_event_id,
+ retry=self._retry,
+ )
+
+ # NOTE: as per the SSE spec, do not reset last_event_id.
+ self._event = ""
+ self._data = []
+ self._retry = None
+
+ return sse
+
+ if line.startswith(":"):
+ return None
+
+ fieldname, _, value = line.partition(":")
+
+ if value.startswith(" "):
+ value = value[1:]
+
+ if fieldname == "event":
+ self._event = value
+ elif fieldname == "data":
+ self._data.append(value)
+ elif fieldname == "id":
+ if "\0" in value:
+ pass
+ else:
+ self._last_event_id = value
+ elif fieldname == "retry":
+ try:
+ self._retry = int(value)
+ except (TypeError, ValueError):
+ pass
+ else:
+ pass # Field is ignored.
+
+ return None
diff --git a/skyvault/skyflow/generated/rest/types/resource_id.py b/common/generated/rest/core/http_sse/_exceptions.py
similarity index 51%
rename from skyvault/skyflow/generated/rest/types/resource_id.py
rename to common/generated/rest/core/http_sse/_exceptions.py
index 211b4108..81605a8a 100644
--- a/skyvault/skyflow/generated/rest/types/resource_id.py
+++ b/common/generated/rest/core/http_sse/_exceptions.py
@@ -1,3 +1,7 @@
# This file was auto-generated by Fern from our API Definition.
-ResourceId = str
+import httpx
+
+
+class SSEError(httpx.TransportError):
+ pass
diff --git a/common/generated/rest/core/http_sse/_models.py b/common/generated/rest/core/http_sse/_models.py
new file mode 100644
index 00000000..1af57f8f
--- /dev/null
+++ b/common/generated/rest/core/http_sse/_models.py
@@ -0,0 +1,17 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import json
+from dataclasses import dataclass
+from typing import Any, Optional
+
+
+@dataclass(frozen=True)
+class ServerSentEvent:
+ event: str = "message"
+ data: str = ""
+ id: str = ""
+ retry: Optional[int] = None
+
+ def json(self) -> Any:
+ """Parse the data field as JSON."""
+ return json.loads(self.data)
diff --git a/common/generated/rest/core/jsonable_encoder.py b/common/generated/rest/core/jsonable_encoder.py
index afee3662..f638cc9a 100644
--- a/common/generated/rest/core/jsonable_encoder.py
+++ b/common/generated/rest/core/jsonable_encoder.py
@@ -15,6 +15,7 @@
from pathlib import PurePath
from types import GeneratorType
from typing import Any, Callable, Dict, List, Optional, Set, Union
+from urllib.parse import quote
import pydantic
from .datetime_utils import serialize_datetime
@@ -30,6 +31,10 @@
def jsonable_encoder(obj: Any, custom_encoder: Optional[Dict[Any, Callable[[Any], Any]]] = None) -> Any:
custom_encoder = custom_encoder or {}
+ # Generated SDKs use Ellipsis (`...`) as the sentinel value for "OMIT".
+ # OMIT values should be excluded from serialized payloads.
+ if obj is Ellipsis:
+ return None
if custom_encoder:
if type(obj) in custom_encoder:
return custom_encoder[type(obj)](obj)
@@ -70,6 +75,8 @@ def jsonable_encoder(obj: Any, custom_encoder: Optional[Dict[Any, Callable[[Any]
allowed_keys = set(obj.keys())
for key, value in obj.items():
if key in allowed_keys:
+ if value is Ellipsis:
+ continue
encoded_key = jsonable_encoder(key, custom_encoder=custom_encoder)
encoded_value = jsonable_encoder(value, custom_encoder=custom_encoder)
encoded_dict[encoded_key] = encoded_value
@@ -77,6 +84,8 @@ def jsonable_encoder(obj: Any, custom_encoder: Optional[Dict[Any, Callable[[Any]
if isinstance(obj, (list, set, frozenset, GeneratorType, tuple)):
encoded_list = []
for item in obj:
+ if item is Ellipsis:
+ continue
encoded_list.append(jsonable_encoder(item, custom_encoder=custom_encoder))
return encoded_list
@@ -98,3 +107,27 @@ def fallback_serializer(o: Any) -> Any:
return jsonable_encoder(data, custom_encoder=custom_encoder)
return to_jsonable_with_fallback(obj, fallback_serializer)
+
+
+def encode_path_param(obj: Any) -> str:
+ """Encode a value for use in a URL path segment.
+
+ Ensures proper string conversion for all types, including
+ booleans which need lowercase 'true'/'false' rather than
+ Python's 'True'/'False'.
+ """
+ if isinstance(obj, bool):
+ return "true" if obj else "false"
+ return str(jsonable_encoder(obj))
+
+
+def quote_path_param(obj: Any) -> str:
+ """Encode a value for use in a URL path segment, percent-encoding it.
+
+ Same as encode_path_param, except the result is percent-encoded so
+ that a value containing "/" or ".." cannot change which endpoint
+ the request resolves to.
+ """
+ if isinstance(obj, bool):
+ return "true" if obj else "false"
+ return quote(str(jsonable_encoder(obj)), safe="")
diff --git a/common/generated/rest/core/logging.py b/common/generated/rest/core/logging.py
new file mode 100644
index 00000000..e5e57245
--- /dev/null
+++ b/common/generated/rest/core/logging.py
@@ -0,0 +1,107 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import logging
+import typing
+
+LogLevel = typing.Literal["debug", "info", "warn", "error"]
+
+_LOG_LEVEL_MAP: typing.Dict[LogLevel, int] = {
+ "debug": 1,
+ "info": 2,
+ "warn": 3,
+ "error": 4,
+}
+
+
+class ILogger(typing.Protocol):
+ def debug(self, message: str, **kwargs: typing.Any) -> None: ...
+ def info(self, message: str, **kwargs: typing.Any) -> None: ...
+ def warn(self, message: str, **kwargs: typing.Any) -> None: ...
+ def error(self, message: str, **kwargs: typing.Any) -> None: ...
+
+
+class ConsoleLogger:
+ _logger: logging.Logger
+
+ def __init__(self) -> None:
+ self._logger = logging.getLogger("fern")
+ if not self._logger.handlers:
+ handler = logging.StreamHandler()
+ handler.setFormatter(logging.Formatter("%(levelname)s - %(message)s"))
+ self._logger.addHandler(handler)
+ self._logger.setLevel(logging.DEBUG)
+
+ def debug(self, message: str, **kwargs: typing.Any) -> None:
+ self._logger.debug(message, extra=kwargs)
+
+ def info(self, message: str, **kwargs: typing.Any) -> None:
+ self._logger.info(message, extra=kwargs)
+
+ def warn(self, message: str, **kwargs: typing.Any) -> None:
+ self._logger.warning(message, extra=kwargs)
+
+ def error(self, message: str, **kwargs: typing.Any) -> None:
+ self._logger.error(message, extra=kwargs)
+
+
+class LogConfig(typing.TypedDict, total=False):
+ level: LogLevel
+ logger: ILogger
+ silent: bool
+
+
+class Logger:
+ _level: int
+ _logger: ILogger
+ _silent: bool
+
+ def __init__(self, *, level: LogLevel, logger: ILogger, silent: bool) -> None:
+ self._level = _LOG_LEVEL_MAP[level]
+ self._logger = logger
+ self._silent = silent
+
+ def _should_log(self, level: LogLevel) -> bool:
+ return not self._silent and self._level <= _LOG_LEVEL_MAP[level]
+
+ def is_debug(self) -> bool:
+ return self._should_log("debug")
+
+ def is_info(self) -> bool:
+ return self._should_log("info")
+
+ def is_warn(self) -> bool:
+ return self._should_log("warn")
+
+ def is_error(self) -> bool:
+ return self._should_log("error")
+
+ def debug(self, message: str, **kwargs: typing.Any) -> None:
+ if self.is_debug():
+ self._logger.debug(message, **kwargs)
+
+ def info(self, message: str, **kwargs: typing.Any) -> None:
+ if self.is_info():
+ self._logger.info(message, **kwargs)
+
+ def warn(self, message: str, **kwargs: typing.Any) -> None:
+ if self.is_warn():
+ self._logger.warn(message, **kwargs)
+
+ def error(self, message: str, **kwargs: typing.Any) -> None:
+ if self.is_error():
+ self._logger.error(message, **kwargs)
+
+
+_default_logger: Logger = Logger(level="info", logger=ConsoleLogger(), silent=True)
+
+
+def create_logger(config: typing.Optional[typing.Union[LogConfig, Logger]] = None) -> Logger:
+ if config is None:
+ return _default_logger
+ if isinstance(config, Logger):
+ return config
+ return Logger(
+ level=config.get("level", "info"),
+ logger=config.get("logger", ConsoleLogger()),
+ silent=config.get("silent", True),
+ )
diff --git a/common/generated/rest/core/parse_error.py b/common/generated/rest/core/parse_error.py
new file mode 100644
index 00000000..4527c6a8
--- /dev/null
+++ b/common/generated/rest/core/parse_error.py
@@ -0,0 +1,36 @@
+# This file was auto-generated by Fern from our API Definition.
+
+from typing import Any, Dict, Optional
+
+
+class ParsingError(Exception):
+ """
+ Raised when the SDK fails to parse/validate a response from the server.
+ This typically indicates that the server returned a response whose shape
+ does not match the expected schema.
+ """
+
+ headers: Optional[Dict[str, str]]
+ status_code: Optional[int]
+ body: Any
+ cause: Optional[Exception]
+
+ def __init__(
+ self,
+ *,
+ headers: Optional[Dict[str, str]] = None,
+ status_code: Optional[int] = None,
+ body: Any = None,
+ cause: Optional[Exception] = None,
+ ) -> None:
+ self.headers = headers
+ self.status_code = status_code
+ self.body = body
+ self.cause = cause
+ super().__init__()
+ if cause is not None:
+ self.__cause__ = cause
+
+ def __str__(self) -> str:
+ cause_str = f", cause: {self.cause}" if self.cause is not None else ""
+ return f"headers: {self.headers}, status_code: {self.status_code}, body: {self.body}{cause_str}"
diff --git a/common/generated/rest/core/pydantic_utilities.py b/common/generated/rest/core/pydantic_utilities.py
index 7db29500..70816b99 100644
--- a/common/generated/rest/core/pydantic_utilities.py
+++ b/common/generated/rest/core/pydantic_utilities.py
@@ -2,30 +2,130 @@
# nopycln: file
import datetime as dt
+import inspect
+import json
+import logging
+import weakref
from collections import defaultdict
-from typing import Any, Callable, ClassVar, Dict, List, Mapping, Optional, Set, Tuple, Type, TypeVar, Union, cast
+from dataclasses import asdict
+from typing import (
+ TYPE_CHECKING,
+ Any,
+ Callable,
+ ClassVar,
+ Dict,
+ List,
+ Mapping,
+ Optional,
+ Set,
+ Tuple,
+ Type,
+ TypeVar,
+ Union,
+ cast,
+)
import pydantic
+import typing_extensions
+from pydantic.fields import FieldInfo as _FieldInfo
+
+_logger = logging.getLogger(__name__)
+
+if TYPE_CHECKING:
+ from .http_sse._models import ServerSentEvent
IS_PYDANTIC_V2 = pydantic.VERSION.startswith("2.")
if IS_PYDANTIC_V2:
- from pydantic.v1.datetime_parse import parse_date as parse_date
- from pydantic.v1.datetime_parse import parse_datetime as parse_datetime
- from pydantic.v1.fields import ModelField as ModelField
- from pydantic.v1.json import ENCODERS_BY_TYPE as encoders_by_type # type: ignore[attr-defined]
- from pydantic.v1.typing import get_args as get_args
- from pydantic.v1.typing import get_origin as get_origin
- from pydantic.v1.typing import is_literal_type as is_literal_type
- from pydantic.v1.typing import is_union as is_union
+ _datetime_adapter = pydantic.TypeAdapter(dt.datetime) # type: ignore[attr-defined]
+ _date_adapter = pydantic.TypeAdapter(dt.date) # type: ignore[attr-defined]
+
+ def parse_datetime(value: Any) -> dt.datetime: # type: ignore[misc]
+ if isinstance(value, dt.datetime):
+ return value
+ return _datetime_adapter.validate_python(value)
+
+ def parse_date(value: Any) -> dt.date: # type: ignore[misc]
+ if isinstance(value, dt.datetime):
+ return value.date()
+ if isinstance(value, dt.date):
+ return value
+ return _date_adapter.validate_python(value)
+
+ # Avoid importing from pydantic.v1 to maintain Python 3.14 compatibility.
+ from typing import get_args as get_args # type: ignore[assignment]
+ from typing import get_origin as get_origin # type: ignore[assignment]
+
+ def is_literal_type(tp: Optional[Type[Any]]) -> bool: # type: ignore[misc]
+ return typing_extensions.get_origin(tp) is typing_extensions.Literal
+
+ def is_union(tp: Optional[Type[Any]]) -> bool: # type: ignore[misc]
+ return tp is Union or typing_extensions.get_origin(tp) is Union # type: ignore[comparison-overlap]
+
+ # Inline encoders_by_type to avoid importing from pydantic.v1.json
+ import re as _re
+ from collections import deque as _deque
+ from decimal import Decimal as _Decimal
+ from enum import Enum as _Enum
+ from ipaddress import (
+ IPv4Address as _IPv4Address,
+ )
+ from ipaddress import (
+ IPv4Interface as _IPv4Interface,
+ )
+ from ipaddress import (
+ IPv4Network as _IPv4Network,
+ )
+ from ipaddress import (
+ IPv6Address as _IPv6Address,
+ )
+ from ipaddress import (
+ IPv6Interface as _IPv6Interface,
+ )
+ from ipaddress import (
+ IPv6Network as _IPv6Network,
+ )
+ from pathlib import Path as _Path
+ from types import GeneratorType as _GeneratorType
+ from uuid import UUID as _UUID
+
+ from pydantic.fields import FieldInfo as ModelField # type: ignore[no-redef, assignment]
+
+ def _decimal_encoder(dec_value: Any) -> Any:
+ if dec_value.as_tuple().exponent >= 0:
+ return int(dec_value)
+ return float(dec_value)
+
+ encoders_by_type: Dict[Type[Any], Callable[[Any], Any]] = { # type: ignore[no-redef]
+ bytes: lambda o: o.decode(),
+ dt.date: lambda o: o.isoformat(),
+ dt.datetime: lambda o: o.isoformat(),
+ dt.time: lambda o: o.isoformat(),
+ dt.timedelta: lambda td: td.total_seconds(),
+ _Decimal: _decimal_encoder,
+ _Enum: lambda o: o.value,
+ frozenset: list,
+ _deque: list,
+ _GeneratorType: list,
+ _IPv4Address: str,
+ _IPv4Interface: str,
+ _IPv4Network: str,
+ _IPv6Address: str,
+ _IPv6Interface: str,
+ _IPv6Network: str,
+ _Path: str,
+ _re.Pattern: lambda o: o.pattern,
+ set: list,
+ _UUID: str,
+ }
else:
from pydantic.datetime_parse import parse_date as parse_date # type: ignore[no-redef]
from pydantic.datetime_parse import parse_datetime as parse_datetime # type: ignore[no-redef]
- from pydantic.fields import ModelField as ModelField # type: ignore[attr-defined, no-redef]
+ from pydantic.fields import ModelField as ModelField # type: ignore[attr-defined, no-redef, assignment]
from pydantic.json import ENCODERS_BY_TYPE as encoders_by_type # type: ignore[no-redef]
from pydantic.typing import get_args as get_args # type: ignore[no-redef]
from pydantic.typing import get_origin as get_origin # type: ignore[no-redef]
- from pydantic.typing import is_literal_type as is_literal_type # type: ignore[no-redef]
+ from pydantic.typing import is_literal_type as is_literal_type # type: ignore[no-redef, assignment]
from pydantic.typing import is_union as is_union # type: ignore[no-redef]
from .datetime_utils import serialize_datetime
@@ -36,11 +136,128 @@
Model = TypeVar("Model", bound=pydantic.BaseModel)
+def parse_sse_obj(sse: "ServerSentEvent", type_: Type[T]) -> T:
+ """
+ Parse a ServerSentEvent into the appropriate type.
+
+ This function handles data-level discrimination where the discriminator
+ (e.g., 'type') is inside the 'data' payload. It parses the SSE data field
+ as JSON and deserializes it into the target type.
+
+ Note: Protocol-level discrimination (where the discriminator comes from
+ the SSE event: field) is handled at code-generation time and does not
+ use this function.
+
+ Args:
+ sse: The ServerSentEvent object to parse
+ type_: The target type to deserialize into
+
+ Returns:
+ The parsed object of type T
+
+ Note:
+ This function is only available in SDK contexts where http_sse module exists.
+ """
+ sse_event = asdict(sse)
+ data_value = sse_event.get("data")
+ if isinstance(data_value, str) and data_value:
+ try:
+ parsed_data = json.loads(data_value)
+ return parse_obj_as(type_, parsed_data)
+ except json.JSONDecodeError as e:
+ _logger.warning(
+ "Failed to parse SSE data field as JSON: %s, data: %s",
+ e,
+ data_value[:100] if len(data_value) > 100 else data_value,
+ )
+ return parse_obj_as(type_, sse_event)
+
+
+_type_adapter_cache: Dict[int, Any] = {}
+
+
+def _get_type_adapter(type_: Type[Any]) -> Any:
+ key = id(type_)
+ adapter = _type_adapter_cache.get(key)
+ if adapter is None:
+ adapter = pydantic.TypeAdapter(type_) # type: ignore[attr-defined]
+ _type_adapter_cache[key] = adapter
+ return adapter
+
+
+_field_alias_cache: "weakref.WeakKeyDictionary[type, Tuple[Dict[str, str], Tuple[str, ...]]]" = (
+ weakref.WeakKeyDictionary()
+)
+
+
+def _get_field_aliases(model: type) -> Tuple[Dict[str, str], Tuple[str, ...]]:
+ """
+ Map of field name to Pydantic alias for the fields whose alias differs from their name, together with the
+ keys that are ambiguous (an alias of one field and the name of another). Computed once per model class.
+ """
+ cached = _field_alias_cache.get(model)
+ if cached is None:
+ fields: Mapping[str, Any] = (
+ getattr(model, "model_fields", {}) if IS_PYDANTIC_V2 else getattr(model, "__fields__", {})
+ )
+ name_to_alias: Dict[str, str] = {}
+ for name, field in fields.items():
+ alias = getattr(field, "alias", None)
+ if alias is not None and alias != name:
+ name_to_alias[name] = alias
+ cached = (name_to_alias, tuple(alias for alias in name_to_alias.values() if alias in fields))
+ _field_alias_cache[model] = cached
+ return cached
+
+
+def _coerce_keys_to_aliases(model: type, data: Any) -> Any:
+ """
+ Accept Python field names in input by rewriting them to their Pydantic aliases,
+ while avoiding silent collisions when a key could refer to multiple fields.
+ """
+ if not isinstance(data, Mapping):
+ return data
+
+ name_to_alias, ambiguous_keys = _get_field_aliases(model)
+ for key in ambiguous_keys:
+ if key in data and name_to_alias.get(key, key) not in data:
+ raise ValueError(
+ f"Ambiguous input key '{key}': it is both a field name and an alias. "
+ "Provide the explicit alias key to disambiguate."
+ )
+
+ if not name_to_alias or not any(name in data for name in name_to_alias):
+ return data if isinstance(data, dict) else dict(data)
+
+ rewritten: Dict[str, Any] = dict(data)
+ for name, alias in name_to_alias.items():
+ if name in data and alias not in rewritten:
+ rewritten[alias] = rewritten.pop(name)
+
+ return rewritten
+
+
def parse_obj_as(type_: Type[T], object_: Any) -> T:
- dealiased_object = convert_and_respect_annotation_metadata(object_=object_, annotation=type_, direction="read")
+ # convert_and_respect_annotation_metadata is required for TypedDict aliasing.
+ #
+ # For Pydantic models, whether we should pre-dealias depends on how the model encodes aliasing:
+ # - If the model uses real Pydantic aliases (pydantic.Field(alias=...)), then we must pass wire keys through
+ # unchanged so Pydantic can validate them.
+ # - If the model encodes aliasing only via FieldMetadata annotations, then we MUST pre-dealias because Pydantic
+ # will not recognize those aliases during validation.
+ if inspect.isclass(type_) and issubclass(type_, pydantic.BaseModel):
+ has_pydantic_aliases = bool(_get_field_aliases(type_)[0])
+
+ dealiased_object = (
+ object_
+ if has_pydantic_aliases
+ else convert_and_respect_annotation_metadata(object_=object_, annotation=type_, direction="read")
+ )
+ else:
+ dealiased_object = convert_and_respect_annotation_metadata(object_=object_, annotation=type_, direction="read")
if IS_PYDANTIC_V2:
- adapter = pydantic.TypeAdapter(type_) # type: ignore[attr-defined]
- return adapter.validate_python(dealiased_object)
+ adapter = _get_type_adapter(type_)
+ return adapter.validate_python(dealiased_object) # type: ignore[no-any-return]
return pydantic.parse_obj_as(type_, dealiased_object)
@@ -59,9 +276,14 @@ class UniversalBaseModel(pydantic.BaseModel):
protected_namespaces=(),
)
+ @pydantic.model_validator(mode="before") # type: ignore[attr-defined]
+ @classmethod
+ def _coerce_field_names_to_aliases(cls, data: Any) -> Any:
+ return _coerce_keys_to_aliases(cls, data)
+
@pydantic.model_serializer(mode="plain", when_used="json") # type: ignore[attr-defined]
def serialize_model(self) -> Any: # type: ignore[name-defined]
- serialized = self.model_dump()
+ serialized = self.dict() # type: ignore[attr-defined]
data = {k: serialize_datetime(v) if isinstance(v, dt.datetime) else v for k, v in serialized.items()}
return data
@@ -71,6 +293,10 @@ class Config:
smart_union = True
json_encoders = {dt.datetime: serialize_datetime}
+ @pydantic.root_validator(pre=True)
+ def _coerce_field_names_to_aliases(cls, values: Any) -> Any:
+ return _coerce_keys_to_aliases(cls, values) # type: ignore[arg-type]
+
@classmethod
def model_construct(cls: Type["Model"], _fields_set: Optional[Set[str]] = None, **values: Any) -> "Model":
dealiased_object = convert_and_respect_annotation_metadata(object_=values, annotation=cls, direction="read")
@@ -147,7 +373,10 @@ def dict(self, **kwargs: Any) -> Dict[str, Any]:
dict_dump = super().dict(**kwargs_with_defaults_exclude_unset_include_fields)
- return convert_and_respect_annotation_metadata(object_=dict_dump, annotation=self.__class__, direction="write")
+ return cast(
+ Dict[str, Any],
+ convert_and_respect_annotation_metadata(object_=dict_dump, annotation=self.__class__, direction="write"),
+ )
def _union_list_of_pydantic_dicts(source: List[Any], destination: List[Any]) -> List[Any]:
@@ -217,7 +446,9 @@ def universal_root_validator(
) -> Callable[[AnyCallable], AnyCallable]:
def decorator(func: AnyCallable) -> AnyCallable:
if IS_PYDANTIC_V2:
- return cast(AnyCallable, pydantic.model_validator(mode="before" if pre else "after")(func)) # type: ignore[attr-defined]
+ # In Pydantic v2, for RootModel we always use "before" mode
+ # The custom validators transform the input value before the model is created
+ return cast(AnyCallable, pydantic.model_validator(mode="before")(func)) # type: ignore[attr-defined]
return cast(AnyCallable, pydantic.root_validator(pre=pre)(func)) # type: ignore[call-overload]
return decorator
@@ -232,7 +463,7 @@ def decorator(func: AnyCallable) -> AnyCallable:
return decorator
-PydanticField = Union[ModelField, pydantic.fields.FieldInfo]
+PydanticField = Union[ModelField, _FieldInfo]
def _get_model_fields(model: Type["Model"]) -> Mapping[str, PydanticField]:
diff --git a/common/generated/rest/core/request_options.py b/common/generated/rest/core/request_options.py
index 1b388044..caa6f669 100644
--- a/common/generated/rest/core/request_options.py
+++ b/common/generated/rest/core/request_options.py
@@ -14,7 +14,9 @@ class RequestOptions(typing.TypedDict, total=False):
This is used primarily as an optional final parameter for service functions.
Attributes:
- - timeout_in_seconds: int. The number of seconds to await an API call before timing out.
+ - timeout: float. The number of seconds to await an API call before timing out.
+
+ - timeout_in_seconds: int. Deprecated alias for `timeout`; both are in seconds. Prefer `timeout`.
- max_retries: int. The max number of retries to attempt if the API call fails.
@@ -27,9 +29,12 @@ class RequestOptions(typing.TypedDict, total=False):
- chunk_size: int. The size, in bytes, to process each chunk of data being streamed back within the response. This equates to leveraging `chunk_size` within `requests` or `httpx`, and is only leveraged for file downloads.
"""
+ timeout: NotRequired[float]
timeout_in_seconds: NotRequired[int]
max_retries: NotRequired[int]
additional_headers: NotRequired[typing.Dict[str, typing.Any]]
additional_query_parameters: NotRequired[typing.Dict[str, typing.Any]]
additional_body_parameters: NotRequired[typing.Dict[str, typing.Any]]
chunk_size: NotRequired[int]
+ stream_reconnection_enabled: NotRequired[bool]
+ max_stream_reconnection_attempts: NotRequired[int]
diff --git a/common/generated/rest/core/serialization.py b/common/generated/rest/core/serialization.py
index c36e865c..1d753e26 100644
--- a/common/generated/rest/core/serialization.py
+++ b/common/generated/rest/core/serialization.py
@@ -26,6 +26,75 @@ def __init__(self, *, alias: str) -> None:
self.alias = alias
+# Resolving type hints (typing.get_type_hints) is expensive because it eval/compiles
+# forward-reference annotations. The result is constant for a given type, so we cache it.
+# This is critical for hot paths like SSE event parsing, where the same (often large
+# discriminated-union) type is converted on every single event.
+_type_hints_cache: typing.Dict[typing.Any, typing.Dict[str, typing.Any]] = {}
+
+
+def _get_cached_type_hints(expected_type: typing.Any) -> typing.Dict[str, typing.Any]:
+ try:
+ cached = _type_hints_cache.get(expected_type)
+ except TypeError:
+ # Unhashable type; resolve without caching.
+ return _resolve_type_hints(expected_type)
+ if cached is None:
+ cached = _resolve_type_hints(expected_type)
+ _type_hints_cache[expected_type] = cached
+ return cached
+
+
+def _resolve_type_hints(expected_type: typing.Any) -> typing.Dict[str, typing.Any]:
+ try:
+ return typing_extensions.get_type_hints(expected_type, include_extras=True)
+ except NameError:
+ # The type contains a circular reference, so we use the __annotations__ attribute directly.
+ return getattr(expected_type, "__annotations__", {})
+
+
+# Whether convert_and_respect_annotation_metadata can possibly rewrite anything for a given
+# annotation, i.e. whether any reachable model/TypedDict field carries a FieldMetadata alias.
+# This is constant per type, so we cache it and use it to short-circuit the recursive walk.
+_requires_conversion_cache: typing.Dict[typing.Any, bool] = {}
+
+
+def _requires_conversion(type_: typing.Any) -> bool:
+ try:
+ cached = _requires_conversion_cache.get(type_)
+ except TypeError:
+ # Unhashable annotation; compute without caching.
+ return _compute_requires_conversion(type_, set())
+ if cached is None:
+ cached = _compute_requires_conversion(type_, set())
+ _requires_conversion_cache[type_] = cached
+ return cached
+
+
+def _compute_requires_conversion(type_: typing.Any, seen: typing.Set[typing.Any]) -> bool:
+ clean_type = _remove_annotations(type_)
+
+ try:
+ if clean_type in seen:
+ return False
+ seen = seen | {clean_type}
+ except TypeError:
+ # Unhashable type; skip cycle tracking (the type graph is finite in practice).
+ pass
+
+ # Models / TypedDicts: a field alias here means we must dealias; otherwise recurse into fields.
+ if (inspect.isclass(clean_type) and issubclass(clean_type, pydantic.BaseModel)) or typing_extensions.is_typeddict(
+ clean_type
+ ):
+ annotations = _get_cached_type_hints(clean_type)
+ if _get_alias_to_field_name(annotations):
+ return True
+ return any(_compute_requires_conversion(hint, seen) for hint in annotations.values())
+
+ # Containers / unions: recurse into the type arguments (List/Set/Sequence/Dict/Union/etc.).
+ return any(_compute_requires_conversion(arg, seen) for arg in typing_extensions.get_args(clean_type))
+
+
def convert_and_respect_annotation_metadata(
*,
object_: typing.Any,
@@ -57,6 +126,13 @@ def convert_and_respect_annotation_metadata(
return None
if inner_type is None:
inner_type = annotation
+ # The only thing this function ever rewrites is keys that carry a FieldMetadata
+ # alias. If nothing in the (cached) type graph has such an alias, the conversion is
+ # a content-identity transform, so we can skip the entire recursive walk. This is
+ # the hot path for SSE streaming, where a large discriminated union would otherwise
+ # be traversed on every single event.
+ if not _requires_conversion(annotation):
+ return object_
clean_type = _remove_annotations(inner_type)
# Pydantic models
@@ -160,12 +236,7 @@ def _convert_mapping(
direction: typing.Literal["read", "write"],
) -> typing.Mapping[str, object]:
converted_object: typing.Dict[str, object] = {}
- try:
- annotations = typing_extensions.get_type_hints(expected_type, include_extras=True)
- except NameError:
- # The TypedDict contains a circular reference, so
- # we use the __annotations__ attribute directly.
- annotations = getattr(expected_type, "__annotations__", {})
+ annotations = _get_cached_type_hints(expected_type)
aliases_to_field_names = _get_alias_to_field_name(annotations)
for key, value in object_.items():
if direction == "read" and key in aliases_to_field_names:
@@ -221,12 +292,12 @@ def _remove_annotations(type_: typing.Any) -> typing.Any:
def get_alias_to_field_mapping(type_: typing.Any) -> typing.Dict[str, str]:
- annotations = typing_extensions.get_type_hints(type_, include_extras=True)
+ annotations = _get_cached_type_hints(type_)
return _get_alias_to_field_name(annotations)
def get_field_to_alias_mapping(type_: typing.Any) -> typing.Dict[str, str]:
- annotations = typing_extensions.get_type_hints(type_, include_extras=True)
+ annotations = _get_cached_type_hints(type_)
return _get_field_to_alias_name(annotations)
diff --git a/common/generated/rest/environment.py b/common/generated/rest/environment.py
index b1c13812..d03788a0 100644
--- a/common/generated/rest/environment.py
+++ b/common/generated/rest/environment.py
@@ -4,5 +4,5 @@
class SkyflowAuthEnvironment(enum.Enum):
- PRODUCTION = "https://manage.skyflowapis.com"
- SANDBOX = "https://manage.skyflowapis-preview.com"
+ PRODUCTION = "https://%7B%7Bvault_url%7D%7D"
+ SANDBOX = "https://%7B%7Bvault_url%7D%7D"
diff --git a/common/generated/rest/errors/__init__.py b/common/generated/rest/errors/__init__.py
index fdf6196c..8810eed8 100644
--- a/common/generated/rest/errors/__init__.py
+++ b/common/generated/rest/errors/__init__.py
@@ -2,8 +2,41 @@
# isort: skip_file
-from .bad_request_error import BadRequestError
-from .not_found_error import NotFoundError
-from .unauthorized_error import UnauthorizedError
+import typing
+from importlib import import_module
-__all__ = ["BadRequestError", "NotFoundError", "UnauthorizedError"]
+if typing.TYPE_CHECKING:
+ from .bad_request_error import BadRequestError
+ from .internal_server_error import InternalServerError
+ from .not_found_error import NotFoundError
+ from .unauthorized_error import UnauthorizedError
+_dynamic_imports: typing.Dict[str, str] = {
+ "BadRequestError": ".bad_request_error",
+ "InternalServerError": ".internal_server_error",
+ "NotFoundError": ".not_found_error",
+ "UnauthorizedError": ".unauthorized_error",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = ["BadRequestError", "InternalServerError", "NotFoundError", "UnauthorizedError"]
diff --git a/common/generated/rest/errors/bad_request_error.py b/common/generated/rest/errors/bad_request_error.py
index c5d0db48..92449913 100644
--- a/common/generated/rest/errors/bad_request_error.py
+++ b/common/generated/rest/errors/bad_request_error.py
@@ -3,12 +3,9 @@
import typing
from ..core.api_error import ApiError
+from ..types.error_response import ErrorResponse
class BadRequestError(ApiError):
- def __init__(
- self,
- body: typing.Dict[str, typing.Optional[typing.Any]],
- headers: typing.Optional[typing.Dict[str, str]] = None,
- ):
+ def __init__(self, body: ErrorResponse, headers: typing.Optional[typing.Dict[str, str]] = None):
super().__init__(status_code=400, headers=headers, body=body)
diff --git a/common/generated/rest/errors/internal_server_error.py b/common/generated/rest/errors/internal_server_error.py
new file mode 100644
index 00000000..d7a796c6
--- /dev/null
+++ b/common/generated/rest/errors/internal_server_error.py
@@ -0,0 +1,11 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from ..core.api_error import ApiError
+from ..types.error_response import ErrorResponse
+
+
+class InternalServerError(ApiError):
+ def __init__(self, body: ErrorResponse, headers: typing.Optional[typing.Dict[str, str]] = None):
+ super().__init__(status_code=500, headers=headers, body=body)
diff --git a/common/generated/rest/errors/not_found_error.py b/common/generated/rest/errors/not_found_error.py
index 66307415..3b2a2d1f 100644
--- a/common/generated/rest/errors/not_found_error.py
+++ b/common/generated/rest/errors/not_found_error.py
@@ -3,12 +3,9 @@
import typing
from ..core.api_error import ApiError
+from ..types.error_response import ErrorResponse
class NotFoundError(ApiError):
- def __init__(
- self,
- body: typing.Dict[str, typing.Optional[typing.Any]],
- headers: typing.Optional[typing.Dict[str, str]] = None,
- ):
+ def __init__(self, body: ErrorResponse, headers: typing.Optional[typing.Dict[str, str]] = None):
super().__init__(status_code=404, headers=headers, body=body)
diff --git a/common/generated/rest/errors/unauthorized_error.py b/common/generated/rest/errors/unauthorized_error.py
index 3d58c2e6..00a614a3 100644
--- a/common/generated/rest/errors/unauthorized_error.py
+++ b/common/generated/rest/errors/unauthorized_error.py
@@ -3,12 +3,9 @@
import typing
from ..core.api_error import ApiError
+from ..types.error_response import ErrorResponse
class UnauthorizedError(ApiError):
- def __init__(
- self,
- body: typing.Dict[str, typing.Optional[typing.Any]],
- headers: typing.Optional[typing.Dict[str, str]] = None,
- ):
+ def __init__(self, body: ErrorResponse, headers: typing.Optional[typing.Dict[str, str]] = None):
super().__init__(status_code=401, headers=headers, body=body)
diff --git a/common/generated/rest/files_v2/__init__.py b/common/generated/rest/files_v2/__init__.py
new file mode 100644
index 00000000..eb9ad9e9
--- /dev/null
+++ b/common/generated/rest/files_v2/__init__.py
@@ -0,0 +1,49 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .types import (
+ DeidentifyFileRequestV2DataFormat,
+ DeidentifyFileRequestV2DataSource,
+ ReidentifyFileRequestV2DataFormat,
+ ReidentifyFileRequestV2DataSource,
+ )
+_dynamic_imports: typing.Dict[str, str] = {
+ "DeidentifyFileRequestV2DataFormat": ".types",
+ "DeidentifyFileRequestV2DataSource": ".types",
+ "ReidentifyFileRequestV2DataFormat": ".types",
+ "ReidentifyFileRequestV2DataSource": ".types",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = [
+ "DeidentifyFileRequestV2DataFormat",
+ "DeidentifyFileRequestV2DataSource",
+ "ReidentifyFileRequestV2DataFormat",
+ "ReidentifyFileRequestV2DataSource",
+]
diff --git a/common/generated/rest/files_v2/client.py b/common/generated/rest/files_v2/client.py
new file mode 100644
index 00000000..250fb259
--- /dev/null
+++ b/common/generated/rest/files_v2/client.py
@@ -0,0 +1,515 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from ..core.request_options import RequestOptions
+from ..types.deidentify_file_response_v2 import DeidentifyFileResponseV2
+from ..types.detect_config_v2 import DetectConfigV2
+from ..types.detect_runs_response_v2 import DetectRunsResponseV2
+from ..types.redaction_level import RedactionLevel
+from ..types.reidentify_file_response_v2 import ReidentifyFileResponseV2
+from .raw_client import AsyncRawFilesV2Client, RawFilesV2Client
+from .types.deidentify_file_request_v2data_format import DeidentifyFileRequestV2DataFormat
+from .types.deidentify_file_request_v2data_source import DeidentifyFileRequestV2DataSource
+from .types.reidentify_file_request_v2data_format import ReidentifyFileRequestV2DataFormat
+from .types.reidentify_file_request_v2data_source import ReidentifyFileRequestV2DataSource
+
+# this is used as the default value for optional parameters
+OMIT = typing.cast(typing.Any, ...)
+
+
+class FilesV2Client:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawFilesV2Client(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawFilesV2Client:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawFilesV2Client
+ """
+ return self._raw_client
+
+ def deidentify_file_v2(
+ self,
+ *,
+ data_source: DeidentifyFileRequestV2DataSource,
+ value: str,
+ data_format: typing.Optional[DeidentifyFileRequestV2DataFormat] = OMIT,
+ configuration_id: typing.Optional[str] = OMIT,
+ configuration: typing.Optional[DetectConfigV2] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> DeidentifyFileResponseV2:
+ """
+ De-identifies sensitive data from a file.
Note:
+ - Layout may vary with token-based redaction for MS Office files (PPT, DOCX, and XLS) and PDFs when token-based PDF processing is selected.
+ - V2 API is in beta.
+
+ Parameters
+ ----------
+ data_source : DeidentifyFileRequestV2DataSource
+ Data source of the input file. `BASE64`: Base64-encoded file string. `SKYFLOW_ID`: Reference file by vault ID. `PRESIGNED_URL`: S3 presigned URL of input file.
+
+ value : str
+ File data corresponding to the specified `dataSource` type.
+
+ data_format : typing.Optional[DeidentifyFileRequestV2DataFormat]
+ Format of the input file. The `VAULT_TOKEN` de-identification type is supported only for `txt`, `json`, `csv`, `xml`, `jsonl`, `docx`, `xlsx`, and `pptx` files.
+
+ configuration_id : typing.Optional[str]
+ ID of the Detect configuration to use for de-identification.
+
+ configuration : typing.Optional[DetectConfigV2]
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ DeidentifyFileResponseV2
+ OK
+
+ Examples
+ --------
+ from skyflow import (
+ Detect,
+ DetectConfigV2,
+ DetectCustomTypes,
+ DetectEntity,
+ DocumentV2,
+ DocumentV2Pdf,
+ EntityTransformation,
+ Media,
+ SkyflowAuth,
+ TransformationShiftDates,
+ )
+
+ client = SkyflowAuth(
+ token="YOUR_TOKEN",
+ )
+ client.files_v2.deidentify_file_v2(
+ data_source="BASE64",
+ value="$BASE64_DATA",
+ data_format="pdf",
+ configuration=DetectConfigV2(
+ vault_id="$VAULT_ID",
+ detect=Detect(
+ entities=[
+ DetectEntity(
+ entity_type="NAME",
+ deidentification_type="VAULT_TOKEN",
+ destination="persons.name",
+ ),
+ DetectEntity(
+ entity_type="DOB",
+ deidentification_type="ENTITY_UNIQUE_COUNTER",
+ transformation=EntityTransformation(
+ shift_dates=TransformationShiftDates(
+ min_days=10,
+ max_days=30,
+ ),
+ ),
+ ),
+ DetectEntity(
+ entity_type="ALL",
+ deidentification_type="ENTITY_UNIQUE_COUNTER",
+ ),
+ ],
+ restrict=["restrict"],
+ skip=["skip"],
+ custom_types=[
+ DetectCustomTypes(
+ label="EMPLOYEE_ID",
+ match=["EMP-[0-9]{6}"],
+ )
+ ],
+ return_entities="EXCLUDE_SENSITIVE_DATA",
+ ),
+ media=Media(
+ document=DocumentV2(
+ pdf=DocumentV2Pdf(
+ processing_mode="TEXT_LAYER",
+ density=200,
+ max_resolution=3000,
+ ),
+ ),
+ ),
+ ),
+ )
+ """
+ _response = self._raw_client.deidentify_file_v2(
+ data_source=data_source,
+ value=value,
+ data_format=data_format,
+ configuration_id=configuration_id,
+ configuration=configuration,
+ request_options=request_options,
+ )
+ return _response.data
+
+ def reidentify_file_v2(
+ self,
+ *,
+ data_source: ReidentifyFileRequestV2DataSource,
+ value: str,
+ vault_id: str,
+ data_format: typing.Optional[ReidentifyFileRequestV2DataFormat] = OMIT,
+ redaction_level: typing.Optional[typing.Sequence[RedactionLevel]] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> ReidentifyFileResponseV2:
+ """
+ Re-identifies tokens in a file.
Requires the Detect Invoker, Detect Manager, or Vault Owner role. Re-identifying `vault_token` values also requires a policy that separately grants the Detokenization action, unless the caller has the Vault Owner role.
Note: V2 API is in beta.
+
+ Parameters
+ ----------
+ data_source : ReidentifyFileRequestV2DataSource
+ Data source of the input file. `BASE64`: Base64-encoded file string. `SKYFLOW_ID`: Reference file by vault ID. `PRESIGNED_URL`: S3 presigned URL of input file.
+
+ value : str
+ File data corresponding to the specified `dataSource` type.
+
+ vault_id : str
+ ID of the vault used for de-identification.
+
+ data_format : typing.Optional[ReidentifyFileRequestV2DataFormat]
+ Format of the input file. Limited to the formats that support the `VAULT_TOKEN` de-identification type.
+
+ redaction_level : typing.Optional[typing.Sequence[RedactionLevel]]
+ Replacement patterns or types applied to entity types or token groups during re-identification. Specifies a replacement pattern/type and the token group or entity type it applies to during re-identification. Set `tokenGroupName` for FlowVault and `entityName` for SkyVault. Similarly, set `redactionType` for FlowVault and `redactionPattern` for SkyVaultto specify the replacement.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ ReidentifyFileResponseV2
+ OK
+
+ Examples
+ --------
+ from skyflow import RedactionLevel, SkyflowAuth
+
+ client = SkyflowAuth(
+ token="YOUR_TOKEN",
+ )
+ client.files_v2.reidentify_file_v2(
+ data_source="BASE64",
+ value="$BASE64_DATA",
+ data_format="txt",
+ vault_id="$VAULT_ID",
+ redaction_level=[
+ RedactionLevel(
+ entity_name="EMAIL_ADDRESS",
+ redaction_type="MASKED",
+ )
+ ],
+ )
+ """
+ _response = self._raw_client.reidentify_file_v2(
+ data_source=data_source,
+ value=value,
+ vault_id=vault_id,
+ data_format=data_format,
+ redaction_level=redaction_level,
+ request_options=request_options,
+ )
+ return _response.data
+
+ def get_run_v2(
+ self, run_id: str, *, vault_id: str, request_options: typing.Optional[RequestOptions] = None
+ ) -> DetectRunsResponseV2:
+ """
+ Returns the status of a detect run.
Note: V2 API is in beta.
+
+ Parameters
+ ----------
+ run_id : str
+
+ vault_id : str
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ DetectRunsResponseV2
+ OK
+
+ Examples
+ --------
+ from skyflow import SkyflowAuth
+
+ client = SkyflowAuth(
+ token="YOUR_TOKEN",
+ )
+ client.files_v2.get_run_v2(
+ run_id="runId",
+ vault_id="vaultId",
+ )
+ """
+ _response = self._raw_client.get_run_v2(run_id, vault_id=vault_id, request_options=request_options)
+ return _response.data
+
+
+class AsyncFilesV2Client:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawFilesV2Client(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawFilesV2Client:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawFilesV2Client
+ """
+ return self._raw_client
+
+ async def deidentify_file_v2(
+ self,
+ *,
+ data_source: DeidentifyFileRequestV2DataSource,
+ value: str,
+ data_format: typing.Optional[DeidentifyFileRequestV2DataFormat] = OMIT,
+ configuration_id: typing.Optional[str] = OMIT,
+ configuration: typing.Optional[DetectConfigV2] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> DeidentifyFileResponseV2:
+ """
+ De-identifies sensitive data from a file.
Note:
+ - Layout may vary with token-based redaction for MS Office files (PPT, DOCX, and XLS) and PDFs when token-based PDF processing is selected.
+ - V2 API is in beta.
+
+ Parameters
+ ----------
+ data_source : DeidentifyFileRequestV2DataSource
+ Data source of the input file. `BASE64`: Base64-encoded file string. `SKYFLOW_ID`: Reference file by vault ID. `PRESIGNED_URL`: S3 presigned URL of input file.
+
+ value : str
+ File data corresponding to the specified `dataSource` type.
+
+ data_format : typing.Optional[DeidentifyFileRequestV2DataFormat]
+ Format of the input file. The `VAULT_TOKEN` de-identification type is supported only for `txt`, `json`, `csv`, `xml`, `jsonl`, `docx`, `xlsx`, and `pptx` files.
+
+ configuration_id : typing.Optional[str]
+ ID of the Detect configuration to use for de-identification.
+
+ configuration : typing.Optional[DetectConfigV2]
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ DeidentifyFileResponseV2
+ OK
+
+ Examples
+ --------
+ import asyncio
+
+ from skyflow import (
+ AsyncSkyflowAuth,
+ Detect,
+ DetectConfigV2,
+ DetectCustomTypes,
+ DetectEntity,
+ DocumentV2,
+ DocumentV2Pdf,
+ EntityTransformation,
+ Media,
+ TransformationShiftDates,
+ )
+
+ client = AsyncSkyflowAuth(
+ token="YOUR_TOKEN",
+ )
+
+
+ async def main() -> None:
+ await client.files_v2.deidentify_file_v2(
+ data_source="BASE64",
+ value="$BASE64_DATA",
+ data_format="pdf",
+ configuration=DetectConfigV2(
+ vault_id="$VAULT_ID",
+ detect=Detect(
+ entities=[
+ DetectEntity(
+ entity_type="NAME",
+ deidentification_type="VAULT_TOKEN",
+ destination="persons.name",
+ ),
+ DetectEntity(
+ entity_type="DOB",
+ deidentification_type="ENTITY_UNIQUE_COUNTER",
+ transformation=EntityTransformation(
+ shift_dates=TransformationShiftDates(
+ min_days=10,
+ max_days=30,
+ ),
+ ),
+ ),
+ DetectEntity(
+ entity_type="ALL",
+ deidentification_type="ENTITY_UNIQUE_COUNTER",
+ ),
+ ],
+ restrict=["restrict"],
+ skip=["skip"],
+ custom_types=[
+ DetectCustomTypes(
+ label="EMPLOYEE_ID",
+ match=["EMP-[0-9]{6}"],
+ )
+ ],
+ return_entities="EXCLUDE_SENSITIVE_DATA",
+ ),
+ media=Media(
+ document=DocumentV2(
+ pdf=DocumentV2Pdf(
+ processing_mode="TEXT_LAYER",
+ density=200,
+ max_resolution=3000,
+ ),
+ ),
+ ),
+ ),
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.deidentify_file_v2(
+ data_source=data_source,
+ value=value,
+ data_format=data_format,
+ configuration_id=configuration_id,
+ configuration=configuration,
+ request_options=request_options,
+ )
+ return _response.data
+
+ async def reidentify_file_v2(
+ self,
+ *,
+ data_source: ReidentifyFileRequestV2DataSource,
+ value: str,
+ vault_id: str,
+ data_format: typing.Optional[ReidentifyFileRequestV2DataFormat] = OMIT,
+ redaction_level: typing.Optional[typing.Sequence[RedactionLevel]] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> ReidentifyFileResponseV2:
+ """
+ Re-identifies tokens in a file.
Requires the Detect Invoker, Detect Manager, or Vault Owner role. Re-identifying `vault_token` values also requires a policy that separately grants the Detokenization action, unless the caller has the Vault Owner role.
Note: V2 API is in beta.
+
+ Parameters
+ ----------
+ data_source : ReidentifyFileRequestV2DataSource
+ Data source of the input file. `BASE64`: Base64-encoded file string. `SKYFLOW_ID`: Reference file by vault ID. `PRESIGNED_URL`: S3 presigned URL of input file.
+
+ value : str
+ File data corresponding to the specified `dataSource` type.
+
+ vault_id : str
+ ID of the vault used for de-identification.
+
+ data_format : typing.Optional[ReidentifyFileRequestV2DataFormat]
+ Format of the input file. Limited to the formats that support the `VAULT_TOKEN` de-identification type.
+
+ redaction_level : typing.Optional[typing.Sequence[RedactionLevel]]
+ Replacement patterns or types applied to entity types or token groups during re-identification. Specifies a replacement pattern/type and the token group or entity type it applies to during re-identification. Set `tokenGroupName` for FlowVault and `entityName` for SkyVault. Similarly, set `redactionType` for FlowVault and `redactionPattern` for SkyVaultto specify the replacement.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ ReidentifyFileResponseV2
+ OK
+
+ Examples
+ --------
+ import asyncio
+
+ from skyflow import AsyncSkyflowAuth, RedactionLevel
+
+ client = AsyncSkyflowAuth(
+ token="YOUR_TOKEN",
+ )
+
+
+ async def main() -> None:
+ await client.files_v2.reidentify_file_v2(
+ data_source="BASE64",
+ value="$BASE64_DATA",
+ data_format="txt",
+ vault_id="$VAULT_ID",
+ redaction_level=[
+ RedactionLevel(
+ entity_name="EMAIL_ADDRESS",
+ redaction_type="MASKED",
+ )
+ ],
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.reidentify_file_v2(
+ data_source=data_source,
+ value=value,
+ vault_id=vault_id,
+ data_format=data_format,
+ redaction_level=redaction_level,
+ request_options=request_options,
+ )
+ return _response.data
+
+ async def get_run_v2(
+ self, run_id: str, *, vault_id: str, request_options: typing.Optional[RequestOptions] = None
+ ) -> DetectRunsResponseV2:
+ """
+ Returns the status of a detect run.
Note: V2 API is in beta.
+
+ Parameters
+ ----------
+ run_id : str
+
+ vault_id : str
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ DetectRunsResponseV2
+ OK
+
+ Examples
+ --------
+ import asyncio
+
+ from skyflow import AsyncSkyflowAuth
+
+ client = AsyncSkyflowAuth(
+ token="YOUR_TOKEN",
+ )
+
+
+ async def main() -> None:
+ await client.files_v2.get_run_v2(
+ run_id="runId",
+ vault_id="vaultId",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.get_run_v2(run_id, vault_id=vault_id, request_options=request_options)
+ return _response.data
diff --git a/common/generated/rest/files_v2/raw_client.py b/common/generated/rest/files_v2/raw_client.py
new file mode 100644
index 00000000..73756b02
--- /dev/null
+++ b/common/generated/rest/files_v2/raw_client.py
@@ -0,0 +1,634 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+from json.decoder import JSONDecodeError
+
+from ..core.api_error import ApiError
+from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from ..core.http_response import AsyncHttpResponse, HttpResponse
+from ..core.jsonable_encoder import encode_path_param
+from ..core.parse_error import ParsingError
+from ..core.pydantic_utilities import parse_obj_as
+from ..core.request_options import RequestOptions
+from ..core.serialization import convert_and_respect_annotation_metadata
+from ..errors.bad_request_error import BadRequestError
+from ..errors.internal_server_error import InternalServerError
+from ..errors.unauthorized_error import UnauthorizedError
+from ..types.deidentify_file_response_v2 import DeidentifyFileResponseV2
+from ..types.detect_config_v2 import DetectConfigV2
+from ..types.detect_runs_response_v2 import DetectRunsResponseV2
+from ..types.error_response import ErrorResponse
+from ..types.redaction_level import RedactionLevel
+from ..types.reidentify_file_response_v2 import ReidentifyFileResponseV2
+from .types.deidentify_file_request_v2data_format import DeidentifyFileRequestV2DataFormat
+from .types.deidentify_file_request_v2data_source import DeidentifyFileRequestV2DataSource
+from .types.reidentify_file_request_v2data_format import ReidentifyFileRequestV2DataFormat
+from .types.reidentify_file_request_v2data_source import ReidentifyFileRequestV2DataSource
+from pydantic import ValidationError
+
+# this is used as the default value for optional parameters
+OMIT = typing.cast(typing.Any, ...)
+
+
+class RawFilesV2Client:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def deidentify_file_v2(
+ self,
+ *,
+ data_source: DeidentifyFileRequestV2DataSource,
+ value: str,
+ data_format: typing.Optional[DeidentifyFileRequestV2DataFormat] = OMIT,
+ configuration_id: typing.Optional[str] = OMIT,
+ configuration: typing.Optional[DetectConfigV2] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[DeidentifyFileResponseV2]:
+ """
+ De-identifies sensitive data from a file.
Note:
+ - Layout may vary with token-based redaction for MS Office files (PPT, DOCX, and XLS) and PDFs when token-based PDF processing is selected.
+ - V2 API is in beta.
+
+ Parameters
+ ----------
+ data_source : DeidentifyFileRequestV2DataSource
+ Data source of the input file. `BASE64`: Base64-encoded file string. `SKYFLOW_ID`: Reference file by vault ID. `PRESIGNED_URL`: S3 presigned URL of input file.
+
+ value : str
+ File data corresponding to the specified `dataSource` type.
+
+ data_format : typing.Optional[DeidentifyFileRequestV2DataFormat]
+ Format of the input file. The `VAULT_TOKEN` de-identification type is supported only for `txt`, `json`, `csv`, `xml`, `jsonl`, `docx`, `xlsx`, and `pptx` files.
+
+ configuration_id : typing.Optional[str]
+ ID of the Detect configuration to use for de-identification.
+
+ configuration : typing.Optional[DetectConfigV2]
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[DeidentifyFileResponseV2]
+ OK
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "v2/detect/deidentify/file",
+ method="POST",
+ json={
+ "dataSource": data_source,
+ "value": value,
+ "dataFormat": data_format,
+ "configurationId": configuration_id,
+ "configuration": convert_and_respect_annotation_metadata(
+ object_=configuration, annotation=DetectConfigV2, direction="write"
+ ),
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ DeidentifyFileResponseV2,
+ parse_obj_as(
+ type_=DeidentifyFileResponseV2, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 400:
+ raise BadRequestError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 401:
+ raise UnauthorizedError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 500:
+ raise InternalServerError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def reidentify_file_v2(
+ self,
+ *,
+ data_source: ReidentifyFileRequestV2DataSource,
+ value: str,
+ vault_id: str,
+ data_format: typing.Optional[ReidentifyFileRequestV2DataFormat] = OMIT,
+ redaction_level: typing.Optional[typing.Sequence[RedactionLevel]] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> HttpResponse[ReidentifyFileResponseV2]:
+ """
+ Re-identifies tokens in a file.
Requires the Detect Invoker, Detect Manager, or Vault Owner role. Re-identifying `vault_token` values also requires a policy that separately grants the Detokenization action, unless the caller has the Vault Owner role.
Note: V2 API is in beta.
+
+ Parameters
+ ----------
+ data_source : ReidentifyFileRequestV2DataSource
+ Data source of the input file. `BASE64`: Base64-encoded file string. `SKYFLOW_ID`: Reference file by vault ID. `PRESIGNED_URL`: S3 presigned URL of input file.
+
+ value : str
+ File data corresponding to the specified `dataSource` type.
+
+ vault_id : str
+ ID of the vault used for de-identification.
+
+ data_format : typing.Optional[ReidentifyFileRequestV2DataFormat]
+ Format of the input file. Limited to the formats that support the `VAULT_TOKEN` de-identification type.
+
+ redaction_level : typing.Optional[typing.Sequence[RedactionLevel]]
+ Replacement patterns or types applied to entity types or token groups during re-identification. Specifies a replacement pattern/type and the token group or entity type it applies to during re-identification. Set `tokenGroupName` for FlowVault and `entityName` for SkyVault. Similarly, set `redactionType` for FlowVault and `redactionPattern` for SkyVaultto specify the replacement.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[ReidentifyFileResponseV2]
+ OK
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ "v2/detect/reidentify/file",
+ method="POST",
+ json={
+ "dataSource": data_source,
+ "value": value,
+ "dataFormat": data_format,
+ "vaultId": vault_id,
+ "redactionLevel": convert_and_respect_annotation_metadata(
+ object_=redaction_level, annotation=typing.Sequence[RedactionLevel], direction="write"
+ ),
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ ReidentifyFileResponseV2,
+ parse_obj_as(
+ type_=ReidentifyFileResponseV2, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 400:
+ raise BadRequestError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 401:
+ raise UnauthorizedError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 500:
+ raise InternalServerError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ def get_run_v2(
+ self, run_id: str, *, vault_id: str, request_options: typing.Optional[RequestOptions] = None
+ ) -> HttpResponse[DetectRunsResponseV2]:
+ """
+ Returns the status of a detect run.
Note: V2 API is in beta.
+
+ Parameters
+ ----------
+ run_id : str
+
+ vault_id : str
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[DetectRunsResponseV2]
+ OK
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"v2/detect/runs/{encode_path_param(run_id)}",
+ method="GET",
+ params={
+ "vaultId": vault_id,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ DetectRunsResponseV2,
+ parse_obj_as(
+ type_=DetectRunsResponseV2, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 400:
+ raise BadRequestError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 401:
+ raise UnauthorizedError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 500:
+ raise InternalServerError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawFilesV2Client:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def deidentify_file_v2(
+ self,
+ *,
+ data_source: DeidentifyFileRequestV2DataSource,
+ value: str,
+ data_format: typing.Optional[DeidentifyFileRequestV2DataFormat] = OMIT,
+ configuration_id: typing.Optional[str] = OMIT,
+ configuration: typing.Optional[DetectConfigV2] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[DeidentifyFileResponseV2]:
+ """
+ De-identifies sensitive data from a file.
Note:
+ - Layout may vary with token-based redaction for MS Office files (PPT, DOCX, and XLS) and PDFs when token-based PDF processing is selected.
+ - V2 API is in beta.
+
+ Parameters
+ ----------
+ data_source : DeidentifyFileRequestV2DataSource
+ Data source of the input file. `BASE64`: Base64-encoded file string. `SKYFLOW_ID`: Reference file by vault ID. `PRESIGNED_URL`: S3 presigned URL of input file.
+
+ value : str
+ File data corresponding to the specified `dataSource` type.
+
+ data_format : typing.Optional[DeidentifyFileRequestV2DataFormat]
+ Format of the input file. The `VAULT_TOKEN` de-identification type is supported only for `txt`, `json`, `csv`, `xml`, `jsonl`, `docx`, `xlsx`, and `pptx` files.
+
+ configuration_id : typing.Optional[str]
+ ID of the Detect configuration to use for de-identification.
+
+ configuration : typing.Optional[DetectConfigV2]
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[DeidentifyFileResponseV2]
+ OK
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "v2/detect/deidentify/file",
+ method="POST",
+ json={
+ "dataSource": data_source,
+ "value": value,
+ "dataFormat": data_format,
+ "configurationId": configuration_id,
+ "configuration": convert_and_respect_annotation_metadata(
+ object_=configuration, annotation=DetectConfigV2, direction="write"
+ ),
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ DeidentifyFileResponseV2,
+ parse_obj_as(
+ type_=DeidentifyFileResponseV2, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ if _response.status_code == 400:
+ raise BadRequestError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 401:
+ raise UnauthorizedError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 500:
+ raise InternalServerError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def reidentify_file_v2(
+ self,
+ *,
+ data_source: ReidentifyFileRequestV2DataSource,
+ value: str,
+ vault_id: str,
+ data_format: typing.Optional[ReidentifyFileRequestV2DataFormat] = OMIT,
+ redaction_level: typing.Optional[typing.Sequence[RedactionLevel]] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> AsyncHttpResponse[ReidentifyFileResponseV2]:
+ """
+ Re-identifies tokens in a file.
Requires the Detect Invoker, Detect Manager, or Vault Owner role. Re-identifying `vault_token` values also requires a policy that separately grants the Detokenization action, unless the caller has the Vault Owner role.
Note: V2 API is in beta.
+
+ Parameters
+ ----------
+ data_source : ReidentifyFileRequestV2DataSource
+ Data source of the input file. `BASE64`: Base64-encoded file string. `SKYFLOW_ID`: Reference file by vault ID. `PRESIGNED_URL`: S3 presigned URL of input file.
+
+ value : str
+ File data corresponding to the specified `dataSource` type.
+
+ vault_id : str
+ ID of the vault used for de-identification.
+
+ data_format : typing.Optional[ReidentifyFileRequestV2DataFormat]
+ Format of the input file. Limited to the formats that support the `VAULT_TOKEN` de-identification type.
+
+ redaction_level : typing.Optional[typing.Sequence[RedactionLevel]]
+ Replacement patterns or types applied to entity types or token groups during re-identification. Specifies a replacement pattern/type and the token group or entity type it applies to during re-identification. Set `tokenGroupName` for FlowVault and `entityName` for SkyVault. Similarly, set `redactionType` for FlowVault and `redactionPattern` for SkyVaultto specify the replacement.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[ReidentifyFileResponseV2]
+ OK
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ "v2/detect/reidentify/file",
+ method="POST",
+ json={
+ "dataSource": data_source,
+ "value": value,
+ "dataFormat": data_format,
+ "vaultId": vault_id,
+ "redactionLevel": convert_and_respect_annotation_metadata(
+ object_=redaction_level, annotation=typing.Sequence[RedactionLevel], direction="write"
+ ),
+ },
+ headers={
+ "content-type": "application/json",
+ },
+ request_options=request_options,
+ omit=OMIT,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ ReidentifyFileResponseV2,
+ parse_obj_as(
+ type_=ReidentifyFileResponseV2, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ if _response.status_code == 400:
+ raise BadRequestError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 401:
+ raise UnauthorizedError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 500:
+ raise InternalServerError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+ async def get_run_v2(
+ self, run_id: str, *, vault_id: str, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncHttpResponse[DetectRunsResponseV2]:
+ """
+ Returns the status of a detect run.
Note: V2 API is in beta.
+
+ Parameters
+ ----------
+ run_id : str
+
+ vault_id : str
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[DetectRunsResponseV2]
+ OK
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"v2/detect/runs/{encode_path_param(run_id)}",
+ method="GET",
+ params={
+ "vaultId": vault_id,
+ },
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ _data = typing.cast(
+ DetectRunsResponseV2,
+ parse_obj_as(
+ type_=DetectRunsResponseV2, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ return AsyncHttpResponse(response=_response, data=_data)
+ if _response.status_code == 400:
+ raise BadRequestError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 401:
+ raise UnauthorizedError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 500:
+ raise InternalServerError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/common/generated/rest/files_v2/types/__init__.py b/common/generated/rest/files_v2/types/__init__.py
new file mode 100644
index 00000000..645b6ea7
--- /dev/null
+++ b/common/generated/rest/files_v2/types/__init__.py
@@ -0,0 +1,47 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .deidentify_file_request_v2data_format import DeidentifyFileRequestV2DataFormat
+ from .deidentify_file_request_v2data_source import DeidentifyFileRequestV2DataSource
+ from .reidentify_file_request_v2data_format import ReidentifyFileRequestV2DataFormat
+ from .reidentify_file_request_v2data_source import ReidentifyFileRequestV2DataSource
+_dynamic_imports: typing.Dict[str, str] = {
+ "DeidentifyFileRequestV2DataFormat": ".deidentify_file_request_v2data_format",
+ "DeidentifyFileRequestV2DataSource": ".deidentify_file_request_v2data_source",
+ "ReidentifyFileRequestV2DataFormat": ".reidentify_file_request_v2data_format",
+ "ReidentifyFileRequestV2DataSource": ".reidentify_file_request_v2data_source",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = [
+ "DeidentifyFileRequestV2DataFormat",
+ "DeidentifyFileRequestV2DataSource",
+ "ReidentifyFileRequestV2DataFormat",
+ "ReidentifyFileRequestV2DataSource",
+]
diff --git a/skyvault/skyflow/generated/rest/types/reidentified_file_output_processed_file_extension.py b/common/generated/rest/files_v2/types/deidentify_file_request_v2data_format.py
similarity index 81%
rename from skyvault/skyflow/generated/rest/types/reidentified_file_output_processed_file_extension.py
rename to common/generated/rest/files_v2/types/deidentify_file_request_v2data_format.py
index c6cbfd02..14b3dfe6 100644
--- a/skyvault/skyflow/generated/rest/types/reidentified_file_output_processed_file_extension.py
+++ b/common/generated/rest/files_v2/types/deidentify_file_request_v2data_format.py
@@ -2,7 +2,7 @@
import typing
-ReidentifiedFileOutputProcessedFileExtension = typing.Union[
+DeidentifyFileRequestV2DataFormat = typing.Union[
typing.Literal[
"mp3",
"wav",
@@ -24,6 +24,9 @@
"pptx",
"xml",
"dcm",
+ "jsonl",
+ "zip",
+ "gif",
],
typing.Any,
]
diff --git a/common/generated/rest/files_v2/types/deidentify_file_request_v2data_source.py b/common/generated/rest/files_v2/types/deidentify_file_request_v2data_source.py
new file mode 100644
index 00000000..143d390a
--- /dev/null
+++ b/common/generated/rest/files_v2/types/deidentify_file_request_v2data_source.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+DeidentifyFileRequestV2DataSource = typing.Union[typing.Literal["BASE64", "SKYFLOW_ID", "PRESIGNED_URL"], typing.Any]
diff --git a/common/generated/rest/files_v2/types/reidentify_file_request_v2data_format.py b/common/generated/rest/files_v2/types/reidentify_file_request_v2data_format.py
new file mode 100644
index 00000000..787c86e3
--- /dev/null
+++ b/common/generated/rest/files_v2/types/reidentify_file_request_v2data_format.py
@@ -0,0 +1,7 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+ReidentifyFileRequestV2DataFormat = typing.Union[
+ typing.Literal["txt", "csv", "json", "xlsx", "docx", "pptx", "xml", "jsonl"], typing.Any
+]
diff --git a/common/generated/rest/files_v2/types/reidentify_file_request_v2data_source.py b/common/generated/rest/files_v2/types/reidentify_file_request_v2data_source.py
new file mode 100644
index 00000000..c80efffc
--- /dev/null
+++ b/common/generated/rest/files_v2/types/reidentify_file_request_v2data_source.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+ReidentifyFileRequestV2DataSource = typing.Union[typing.Literal["BASE64", "SKYFLOW_ID", "PRESIGNED_URL"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/authentication/__init__.py b/common/generated/rest/guardrails_v2/__init__.py
similarity index 100%
rename from skyvault/skyflow/generated/rest/authentication/__init__.py
rename to common/generated/rest/guardrails_v2/__init__.py
diff --git a/skyvault/skyflow/generated/rest/guardrails/client.py b/common/generated/rest/guardrails_v2/client.py
similarity index 71%
rename from skyvault/skyflow/generated/rest/guardrails/client.py
rename to common/generated/rest/guardrails_v2/client.py
index 88cab59d..f6cd62e1 100644
--- a/skyvault/skyflow/generated/rest/guardrails/client.py
+++ b/common/generated/rest/guardrails_v2/client.py
@@ -4,29 +4,29 @@
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.request_options import RequestOptions
-from ..types.detect_guardrails_response import DetectGuardrailsResponse
-from .raw_client import AsyncRawGuardrailsClient, RawGuardrailsClient
+from ..types.detect_guardrails_response_v2 import DetectGuardrailsResponseV2
+from .raw_client import AsyncRawGuardrailsV2Client, RawGuardrailsV2Client
# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)
-class GuardrailsClient:
+class GuardrailsV2Client:
def __init__(self, *, client_wrapper: SyncClientWrapper):
- self._raw_client = RawGuardrailsClient(client_wrapper=client_wrapper)
+ self._raw_client = RawGuardrailsV2Client(client_wrapper=client_wrapper)
@property
- def with_raw_response(self) -> RawGuardrailsClient:
+ def with_raw_response(self) -> RawGuardrailsV2Client:
"""
Retrieves a raw implementation of this client that returns raw responses.
Returns
-------
- RawGuardrailsClient
+ RawGuardrailsV2Client
"""
return self._raw_client
- def check_guardrails(
+ def check_guardrails_v2(
self,
*,
text: str,
@@ -34,9 +34,9 @@ def check_guardrails(
check_toxicity: typing.Optional[bool] = OMIT,
deny_topics: typing.Optional[typing.Sequence[str]] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> DetectGuardrailsResponse:
+ ) -> DetectGuardrailsResponseV2:
"""
- Preserve safety and compliance with usage policies.
+ Preserve safety and compliance with usage policies.
Note: V2 API is in beta.
Parameters
----------
@@ -57,24 +57,24 @@ def check_guardrails(
Returns
-------
- DetectGuardrailsResponse
+ DetectGuardrailsResponseV2
OK
Examples
--------
- from skyflow import Skyflow
+ from skyflow import SkyflowAuth
- client = Skyflow(
+ client = SkyflowAuth(
token="YOUR_TOKEN",
)
- client.guardrails.check_guardrails(
+ client.guardrails_v2.check_guardrails_v2(
text="I love to play cricket.",
check_toxicity=True,
deny_topics=["sports"],
vault_id="$VAULT_ID",
)
"""
- _response = self._raw_client.check_guardrails(
+ _response = self._raw_client.check_guardrails_v2(
text=text,
vault_id=vault_id,
check_toxicity=check_toxicity,
@@ -84,22 +84,22 @@ def check_guardrails(
return _response.data
-class AsyncGuardrailsClient:
+class AsyncGuardrailsV2Client:
def __init__(self, *, client_wrapper: AsyncClientWrapper):
- self._raw_client = AsyncRawGuardrailsClient(client_wrapper=client_wrapper)
+ self._raw_client = AsyncRawGuardrailsV2Client(client_wrapper=client_wrapper)
@property
- def with_raw_response(self) -> AsyncRawGuardrailsClient:
+ def with_raw_response(self) -> AsyncRawGuardrailsV2Client:
"""
Retrieves a raw implementation of this client that returns raw responses.
Returns
-------
- AsyncRawGuardrailsClient
+ AsyncRawGuardrailsV2Client
"""
return self._raw_client
- async def check_guardrails(
+ async def check_guardrails_v2(
self,
*,
text: str,
@@ -107,9 +107,9 @@ async def check_guardrails(
check_toxicity: typing.Optional[bool] = OMIT,
deny_topics: typing.Optional[typing.Sequence[str]] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> DetectGuardrailsResponse:
+ ) -> DetectGuardrailsResponseV2:
"""
- Preserve safety and compliance with usage policies.
+ Preserve safety and compliance with usage policies.
Note: V2 API is in beta.
Parameters
----------
@@ -130,22 +130,22 @@ async def check_guardrails(
Returns
-------
- DetectGuardrailsResponse
+ DetectGuardrailsResponseV2
OK
Examples
--------
import asyncio
- from skyflow import AsyncSkyflow
+ from skyflow import AsyncSkyflowAuth
- client = AsyncSkyflow(
+ client = AsyncSkyflowAuth(
token="YOUR_TOKEN",
)
async def main() -> None:
- await client.guardrails.check_guardrails(
+ await client.guardrails_v2.check_guardrails_v2(
text="I love to play cricket.",
check_toxicity=True,
deny_topics=["sports"],
@@ -155,7 +155,7 @@ async def main() -> None:
asyncio.run(main())
"""
- _response = await self._raw_client.check_guardrails(
+ _response = await self._raw_client.check_guardrails_v2(
text=text,
vault_id=vault_id,
check_toxicity=check_toxicity,
diff --git a/skyvault/skyflow/generated/rest/guardrails/raw_client.py b/common/generated/rest/guardrails_v2/raw_client.py
similarity index 76%
rename from skyvault/skyflow/generated/rest/guardrails/raw_client.py
rename to common/generated/rest/guardrails_v2/raw_client.py
index 1328b1b8..6f0dd663 100644
--- a/skyvault/skyflow/generated/rest/guardrails/raw_client.py
+++ b/common/generated/rest/guardrails_v2/raw_client.py
@@ -6,23 +6,25 @@
from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.http_response import AsyncHttpResponse, HttpResponse
+from ..core.parse_error import ParsingError
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
from ..errors.bad_request_error import BadRequestError
from ..errors.internal_server_error import InternalServerError
from ..errors.unauthorized_error import UnauthorizedError
-from ..types.detect_guardrails_response import DetectGuardrailsResponse
+from ..types.detect_guardrails_response_v2 import DetectGuardrailsResponseV2
from ..types.error_response import ErrorResponse
+from pydantic import ValidationError
# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)
-class RawGuardrailsClient:
+class RawGuardrailsV2Client:
def __init__(self, *, client_wrapper: SyncClientWrapper):
self._client_wrapper = client_wrapper
- def check_guardrails(
+ def check_guardrails_v2(
self,
*,
text: str,
@@ -30,9 +32,9 @@ def check_guardrails(
check_toxicity: typing.Optional[bool] = OMIT,
deny_topics: typing.Optional[typing.Sequence[str]] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[DetectGuardrailsResponse]:
+ ) -> HttpResponse[DetectGuardrailsResponseV2]:
"""
- Preserve safety and compliance with usage policies.
+ Preserve safety and compliance with usage policies.
Note: V2 API is in beta.
Parameters
----------
@@ -53,17 +55,17 @@ def check_guardrails(
Returns
-------
- HttpResponse[DetectGuardrailsResponse]
+ HttpResponse[DetectGuardrailsResponseV2]
OK
"""
_response = self._client_wrapper.httpx_client.request(
- "v1/detect/guardrails",
+ "v2/detect/guardrails",
method="POST",
json={
"text": text,
- "check_toxicity": check_toxicity,
- "deny_topics": deny_topics,
- "vault_id": vault_id,
+ "checkToxicity": check_toxicity,
+ "denyTopics": deny_topics,
+ "vaultId": vault_id,
},
headers={
"content-type": "application/json",
@@ -74,9 +76,9 @@ def check_guardrails(
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- DetectGuardrailsResponse,
+ DetectGuardrailsResponseV2,
parse_obj_as(
- type_=DetectGuardrailsResponse, # type: ignore
+ type_=DetectGuardrailsResponseV2, # type: ignore
object_=_response.json(),
),
)
@@ -85,9 +87,9 @@ def check_guardrails(
raise BadRequestError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -96,9 +98,9 @@ def check_guardrails(
raise UnauthorizedError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -117,14 +119,18 @@ def check_guardrails(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-class AsyncRawGuardrailsClient:
+class AsyncRawGuardrailsV2Client:
def __init__(self, *, client_wrapper: AsyncClientWrapper):
self._client_wrapper = client_wrapper
- async def check_guardrails(
+ async def check_guardrails_v2(
self,
*,
text: str,
@@ -132,9 +138,9 @@ async def check_guardrails(
check_toxicity: typing.Optional[bool] = OMIT,
deny_topics: typing.Optional[typing.Sequence[str]] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[DetectGuardrailsResponse]:
+ ) -> AsyncHttpResponse[DetectGuardrailsResponseV2]:
"""
- Preserve safety and compliance with usage policies.
+ Preserve safety and compliance with usage policies.
Note: V2 API is in beta.
Parameters
----------
@@ -155,17 +161,17 @@ async def check_guardrails(
Returns
-------
- AsyncHttpResponse[DetectGuardrailsResponse]
+ AsyncHttpResponse[DetectGuardrailsResponseV2]
OK
"""
_response = await self._client_wrapper.httpx_client.request(
- "v1/detect/guardrails",
+ "v2/detect/guardrails",
method="POST",
json={
"text": text,
- "check_toxicity": check_toxicity,
- "deny_topics": deny_topics,
- "vault_id": vault_id,
+ "checkToxicity": check_toxicity,
+ "denyTopics": deny_topics,
+ "vaultId": vault_id,
},
headers={
"content-type": "application/json",
@@ -176,9 +182,9 @@ async def check_guardrails(
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- DetectGuardrailsResponse,
+ DetectGuardrailsResponseV2,
parse_obj_as(
- type_=DetectGuardrailsResponse, # type: ignore
+ type_=DetectGuardrailsResponseV2, # type: ignore
object_=_response.json(),
),
)
@@ -187,9 +193,9 @@ async def check_guardrails(
raise BadRequestError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -198,9 +204,9 @@ async def check_guardrails(
raise UnauthorizedError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -219,4 +225,8 @@ async def check_guardrails(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/common/generated/rest/raw_client.py b/common/generated/rest/raw_client.py
new file mode 100644
index 00000000..18893ef3
--- /dev/null
+++ b/common/generated/rest/raw_client.py
@@ -0,0 +1,86 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+from json.decoder import JSONDecodeError
+
+from .core.api_error import ApiError
+from .core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .core.http_response import AsyncHttpResponse, HttpResponse
+from .core.jsonable_encoder import encode_path_param
+from .core.parse_error import ParsingError
+from .core.request_options import RequestOptions
+from pydantic import ValidationError
+
+
+class RawSkyflowAuth:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def patch_v2vaults_id(
+ self, vault_id: typing.Optional[str], *, request_options: typing.Optional[RequestOptions] = None
+ ) -> HttpResponse[None]:
+ """
+ Parameters
+ ----------
+ vault_id : typing.Optional[str]
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[None]
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"v2/vaults/{encode_path_param(vault_id)}",
+ method="PATCH",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ return HttpResponse(response=_response, data=None)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawSkyflowAuth:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def patch_v2vaults_id(
+ self, vault_id: typing.Optional[str], *, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncHttpResponse[None]:
+ """
+ Parameters
+ ----------
+ vault_id : typing.Optional[str]
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[None]
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"v2/vaults/{encode_path_param(vault_id)}",
+ method="PATCH",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ return AsyncHttpResponse(response=_response, data=None)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/skyvault/skyflow/generated/rest/bin_lookup/__init__.py b/common/generated/rest/strings_v2/__init__.py
similarity index 100%
rename from skyvault/skyflow/generated/rest/bin_lookup/__init__.py
rename to common/generated/rest/strings_v2/__init__.py
diff --git a/common/generated/rest/strings_v2/client.py b/common/generated/rest/strings_v2/client.py
new file mode 100644
index 00000000..7812e6da
--- /dev/null
+++ b/common/generated/rest/strings_v2/client.py
@@ -0,0 +1,344 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from ..core.request_options import RequestOptions
+from ..types.deidentify_string_response_v2 import DeidentifyStringResponseV2
+from ..types.detect_config_v2 import DetectConfigV2
+from ..types.redaction_level import RedactionLevel
+from ..types.reidentify_string_response_v2 import ReidentifyStringResponseV2
+from .raw_client import AsyncRawStringsV2Client, RawStringsV2Client
+
+# this is used as the default value for optional parameters
+OMIT = typing.cast(typing.Any, ...)
+
+
+class StringsV2Client:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawStringsV2Client(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawStringsV2Client:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawStringsV2Client
+ """
+ return self._raw_client
+
+ def deidentify_string_v2(
+ self,
+ *,
+ text: str,
+ configuration_id: typing.Optional[str] = OMIT,
+ configuration: typing.Optional[DetectConfigV2] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> DeidentifyStringResponseV2:
+ """
+ De-identifies sensitive data from a string.
Note: V2 API is in beta.
+
+ Parameters
+ ----------
+ text : str
+ Text to deidentify.
+
+ configuration_id : typing.Optional[str]
+ ID of the Detect configuration to use for de-identification.
+
+ configuration : typing.Optional[DetectConfigV2]
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ DeidentifyStringResponseV2
+ OK
+
+ Examples
+ --------
+ from skyflow import (
+ Detect,
+ DetectConfigV2,
+ DetectCustomTypes,
+ DetectEntity,
+ EntityTransformation,
+ SkyflowAuth,
+ TransformationShiftDates,
+ )
+
+ client = SkyflowAuth(
+ token="YOUR_TOKEN",
+ )
+ client.strings_v2.deidentify_string_v2(
+ text="My name is John Doe, and my email is johndoe@acme.com.",
+ configuration=DetectConfigV2(
+ vault_id="$VAULT_ID",
+ detect=Detect(
+ entities=[
+ DetectEntity(
+ entity_type="NAME",
+ deidentification_type="VAULT_TOKEN",
+ destination="persons.name",
+ ),
+ DetectEntity(
+ entity_type="DOB",
+ deidentification_type="ENTITY_UNIQUE_COUNTER",
+ transformation=EntityTransformation(
+ shift_dates=TransformationShiftDates(
+ min_days=10,
+ max_days=30,
+ ),
+ ),
+ ),
+ DetectEntity(
+ entity_type="ALL",
+ deidentification_type="ENTITY_UNIQUE_COUNTER",
+ ),
+ ],
+ restrict=["restrict"],
+ skip=["skip"],
+ custom_types=[
+ DetectCustomTypes(
+ label="EMPLOYEE_ID",
+ match=["EMP-[0-9]{6}"],
+ )
+ ],
+ return_entities="EXCLUDE_SENSITIVE_DATA",
+ ),
+ ),
+ )
+ """
+ _response = self._raw_client.deidentify_string_v2(
+ text=text, configuration_id=configuration_id, configuration=configuration, request_options=request_options
+ )
+ return _response.data
+
+ def reidentify_string_v2(
+ self,
+ *,
+ vault_id: str,
+ text: str,
+ redaction_level: typing.Optional[typing.Sequence[RedactionLevel]] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> ReidentifyStringResponseV2:
+ """
+ Re-identifies tokens in a string.
Requires the Detect Invoker, Detect Manager, or Vault Owner role. Re-identifying `vault_token` values also requires a policy that separately grants the Detokenization action, unless the caller has the Vault Owner role.
Note: V2 API is in beta.
+
+ Parameters
+ ----------
+ vault_id : str
+ ID of the vault used for re-identification. Requires the Detect Invoker, Detect Manager, or Vault Owner role for this vault. Re-identifying `vault_token` values also requires a role or policy that separately grants the Detokenization action, unless the caller has the Vault Owner role.
+
+ text : str
+ Text to reidentify.
+
+ redaction_level : typing.Optional[typing.Sequence[RedactionLevel]]
+ Replacement patterns or types applied to entity types or token groups during re-identification. Specifies a replacement pattern/type and the token group or entity type it applies to during re-identification. Set exactly one of `tokenGroupName` or `entityName`. Use `tokenGroupName` for FlowVault and `entityName` for SkyVault. Similarly, set exactly one of `redactionType` or `redactionPattern` to specify the replacement.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ ReidentifyStringResponseV2
+ OK
+
+ Examples
+ --------
+ from skyflow import RedactionLevel, SkyflowAuth
+
+ client = SkyflowAuth(
+ token="YOUR_TOKEN",
+ )
+ client.strings_v2.reidentify_string_v2(
+ vault_id="$VAULT_ID",
+ text="My name is [NAME_1], and my email is [EMAIL_ADDRESS_1].",
+ redaction_level=[
+ RedactionLevel(
+ entity_name="EMAIL_ADDRESS",
+ redaction_type="MASKED",
+ )
+ ],
+ )
+ """
+ _response = self._raw_client.reidentify_string_v2(
+ vault_id=vault_id, text=text, redaction_level=redaction_level, request_options=request_options
+ )
+ return _response.data
+
+
+class AsyncStringsV2Client:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawStringsV2Client(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawStringsV2Client:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawStringsV2Client
+ """
+ return self._raw_client
+
+ async def deidentify_string_v2(
+ self,
+ *,
+ text: str,
+ configuration_id: typing.Optional[str] = OMIT,
+ configuration: typing.Optional[DetectConfigV2] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> DeidentifyStringResponseV2:
+ """
+ De-identifies sensitive data from a string.
Note: V2 API is in beta.
+
+ Parameters
+ ----------
+ text : str
+ Text to deidentify.
+
+ configuration_id : typing.Optional[str]
+ ID of the Detect configuration to use for de-identification.
+
+ configuration : typing.Optional[DetectConfigV2]
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ DeidentifyStringResponseV2
+ OK
+
+ Examples
+ --------
+ import asyncio
+
+ from skyflow import (
+ AsyncSkyflowAuth,
+ Detect,
+ DetectConfigV2,
+ DetectCustomTypes,
+ DetectEntity,
+ EntityTransformation,
+ TransformationShiftDates,
+ )
+
+ client = AsyncSkyflowAuth(
+ token="YOUR_TOKEN",
+ )
+
+
+ async def main() -> None:
+ await client.strings_v2.deidentify_string_v2(
+ text="My name is John Doe, and my email is johndoe@acme.com.",
+ configuration=DetectConfigV2(
+ vault_id="$VAULT_ID",
+ detect=Detect(
+ entities=[
+ DetectEntity(
+ entity_type="NAME",
+ deidentification_type="VAULT_TOKEN",
+ destination="persons.name",
+ ),
+ DetectEntity(
+ entity_type="DOB",
+ deidentification_type="ENTITY_UNIQUE_COUNTER",
+ transformation=EntityTransformation(
+ shift_dates=TransformationShiftDates(
+ min_days=10,
+ max_days=30,
+ ),
+ ),
+ ),
+ DetectEntity(
+ entity_type="ALL",
+ deidentification_type="ENTITY_UNIQUE_COUNTER",
+ ),
+ ],
+ restrict=["restrict"],
+ skip=["skip"],
+ custom_types=[
+ DetectCustomTypes(
+ label="EMPLOYEE_ID",
+ match=["EMP-[0-9]{6}"],
+ )
+ ],
+ return_entities="EXCLUDE_SENSITIVE_DATA",
+ ),
+ ),
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.deidentify_string_v2(
+ text=text, configuration_id=configuration_id, configuration=configuration, request_options=request_options
+ )
+ return _response.data
+
+ async def reidentify_string_v2(
+ self,
+ *,
+ vault_id: str,
+ text: str,
+ redaction_level: typing.Optional[typing.Sequence[RedactionLevel]] = OMIT,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> ReidentifyStringResponseV2:
+ """
+ Re-identifies tokens in a string.
Requires the Detect Invoker, Detect Manager, or Vault Owner role. Re-identifying `vault_token` values also requires a policy that separately grants the Detokenization action, unless the caller has the Vault Owner role.
Note: V2 API is in beta.
+
+ Parameters
+ ----------
+ vault_id : str
+ ID of the vault used for re-identification. Requires the Detect Invoker, Detect Manager, or Vault Owner role for this vault. Re-identifying `vault_token` values also requires a role or policy that separately grants the Detokenization action, unless the caller has the Vault Owner role.
+
+ text : str
+ Text to reidentify.
+
+ redaction_level : typing.Optional[typing.Sequence[RedactionLevel]]
+ Replacement patterns or types applied to entity types or token groups during re-identification. Specifies a replacement pattern/type and the token group or entity type it applies to during re-identification. Set exactly one of `tokenGroupName` or `entityName`. Use `tokenGroupName` for FlowVault and `entityName` for SkyVault. Similarly, set exactly one of `redactionType` or `redactionPattern` to specify the replacement.
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ ReidentifyStringResponseV2
+ OK
+
+ Examples
+ --------
+ import asyncio
+
+ from skyflow import AsyncSkyflowAuth, RedactionLevel
+
+ client = AsyncSkyflowAuth(
+ token="YOUR_TOKEN",
+ )
+
+
+ async def main() -> None:
+ await client.strings_v2.reidentify_string_v2(
+ vault_id="$VAULT_ID",
+ text="My name is [NAME_1], and my email is [EMAIL_ADDRESS_1].",
+ redaction_level=[
+ RedactionLevel(
+ entity_name="EMAIL_ADDRESS",
+ redaction_type="MASKED",
+ )
+ ],
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.reidentify_string_v2(
+ vault_id=vault_id, text=text, redaction_level=redaction_level, request_options=request_options
+ )
+ return _response.data
diff --git a/skyvault/skyflow/generated/rest/strings/raw_client.py b/common/generated/rest/strings_v2/raw_client.py
similarity index 55%
rename from skyvault/skyflow/generated/rest/strings/raw_client.py
rename to common/generated/rest/strings_v2/raw_client.py
index 313c10ce..9418317f 100644
--- a/skyvault/skyflow/generated/rest/strings/raw_client.py
+++ b/common/generated/rest/strings_v2/raw_client.py
@@ -6,92 +6,66 @@
from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.http_response import AsyncHttpResponse, HttpResponse
+from ..core.parse_error import ParsingError
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
from ..core.serialization import convert_and_respect_annotation_metadata
from ..errors.bad_request_error import BadRequestError
from ..errors.internal_server_error import InternalServerError
from ..errors.unauthorized_error import UnauthorizedError
-from ..types.deidentify_string_response import DeidentifyStringResponse
+from ..types.deidentify_string_response_v2 import DeidentifyStringResponseV2
+from ..types.detect_config_v2 import DetectConfigV2
from ..types.error_response import ErrorResponse
-from ..types.format import Format
-from ..types.identify_response import IdentifyResponse
-from ..types.token_type_mapping import TokenTypeMapping
-from ..types.transformations import Transformations
-from .types.deidentify_string_request_entity_types_item import DeidentifyStringRequestEntityTypesItem
+from ..types.redaction_level import RedactionLevel
+from ..types.reidentify_string_response_v2 import ReidentifyStringResponseV2
+from pydantic import ValidationError
# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)
-class RawStringsClient:
+class RawStringsV2Client:
def __init__(self, *, client_wrapper: SyncClientWrapper):
self._client_wrapper = client_wrapper
- def deidentify_string(
+ def deidentify_string_v2(
self,
*,
text: str,
- vault_id: str,
- entity_types: typing.Optional[typing.Sequence[DeidentifyStringRequestEntityTypesItem]] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
configuration_id: typing.Optional[str] = OMIT,
+ configuration: typing.Optional[DetectConfigV2] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[DeidentifyStringResponse]:
+ ) -> HttpResponse[DeidentifyStringResponseV2]:
"""
- De-identifies sensitive data from a string.
+ De-identifies sensitive data from a string.
Note: V2 API is in beta.
Parameters
----------
text : str
- Text to de-identify.
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyStringRequestEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
+ Text to deidentify.
configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
+ ID of the Detect configuration to use for de-identification.
+
+ configuration : typing.Optional[DetectConfigV2]
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- HttpResponse[DeidentifyStringResponse]
+ HttpResponse[DeidentifyStringResponseV2]
OK
"""
_response = self._client_wrapper.httpx_client.request(
- "v1/detect/deidentify/string",
+ "v2/detect/deidentify/string",
method="POST",
json={
"text": text,
- "vault_id": vault_id,
- "entity_types": entity_types,
- "token_type": convert_and_respect_annotation_metadata(
- object_=token_type, annotation=TokenTypeMapping, direction="write"
- ),
- "allow_regex": allow_regex,
- "restrict_regex": restrict_regex,
- "transformations": convert_and_respect_annotation_metadata(
- object_=transformations, annotation=Transformations, direction="write"
+ "configurationId": configuration_id,
+ "configuration": convert_and_respect_annotation_metadata(
+ object_=configuration, annotation=DetectConfigV2, direction="write"
),
- "configuration_id": configuration_id,
},
headers={
"content-type": "application/json",
@@ -102,9 +76,9 @@ def deidentify_string(
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- DeidentifyStringResponse,
+ DeidentifyStringResponseV2,
parse_obj_as(
- type_=DeidentifyStringResponse, # type: ignore
+ type_=DeidentifyStringResponseV2, # type: ignore
object_=_response.json(),
),
)
@@ -113,9 +87,9 @@ def deidentify_string(
raise BadRequestError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -124,9 +98,9 @@ def deidentify_string(
raise UnauthorizedError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -145,44 +119,51 @@ def deidentify_string(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
- def reidentify_string(
+ def reidentify_string_v2(
self,
*,
- text: typing.Optional[str] = OMIT,
- vault_id: typing.Optional[str] = OMIT,
- format: typing.Optional[Format] = OMIT,
+ vault_id: str,
+ text: str,
+ redaction_level: typing.Optional[typing.Sequence[RedactionLevel]] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[IdentifyResponse]:
+ ) -> HttpResponse[ReidentifyStringResponseV2]:
"""
- Re-identifies tokens in a string.
+ Re-identifies tokens in a string.
Requires the Detect Invoker, Detect Manager, or Vault Owner role. Re-identifying `vault_token` values also requires a policy that separately grants the Detokenization action, unless the caller has the Vault Owner role.
Note: V2 API is in beta.
Parameters
----------
- text : typing.Optional[str]
- Text to reidentify.
+ vault_id : str
+ ID of the vault used for re-identification. Requires the Detect Invoker, Detect Manager, or Vault Owner role for this vault. Re-identifying `vault_token` values also requires a role or policy that separately grants the Detokenization action, unless the caller has the Vault Owner role.
- vault_id : typing.Optional[str]
- ID of the vault where the entities are stored.
+ text : str
+ Text to reidentify.
- format : typing.Optional[Format]
+ redaction_level : typing.Optional[typing.Sequence[RedactionLevel]]
+ Replacement patterns or types applied to entity types or token groups during re-identification. Specifies a replacement pattern/type and the token group or entity type it applies to during re-identification. Set exactly one of `tokenGroupName` or `entityName`. Use `tokenGroupName` for FlowVault and `entityName` for SkyVault. Similarly, set exactly one of `redactionType` or `redactionPattern` to specify the replacement.
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- HttpResponse[IdentifyResponse]
+ HttpResponse[ReidentifyStringResponseV2]
OK
"""
_response = self._client_wrapper.httpx_client.request(
- "v1/detect/reidentify/string",
+ "v2/detect/reidentify/string",
method="POST",
json={
+ "vaultId": vault_id,
"text": text,
- "vault_id": vault_id,
- "format": convert_and_respect_annotation_metadata(object_=format, annotation=Format, direction="write"),
+ "redactionLevel": convert_and_respect_annotation_metadata(
+ object_=redaction_level, annotation=typing.Sequence[RedactionLevel], direction="write"
+ ),
},
headers={
"content-type": "application/json",
@@ -193,9 +174,9 @@ def reidentify_string(
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- IdentifyResponse,
+ ReidentifyStringResponseV2,
parse_obj_as(
- type_=IdentifyResponse, # type: ignore
+ type_=ReidentifyStringResponseV2, # type: ignore
object_=_response.json(),
),
)
@@ -204,9 +185,9 @@ def reidentify_string(
raise BadRequestError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -215,9 +196,9 @@ def reidentify_string(
raise UnauthorizedError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -236,77 +217,55 @@ def reidentify_string(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-class AsyncRawStringsClient:
+class AsyncRawStringsV2Client:
def __init__(self, *, client_wrapper: AsyncClientWrapper):
self._client_wrapper = client_wrapper
- async def deidentify_string(
+ async def deidentify_string_v2(
self,
*,
text: str,
- vault_id: str,
- entity_types: typing.Optional[typing.Sequence[DeidentifyStringRequestEntityTypesItem]] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
configuration_id: typing.Optional[str] = OMIT,
+ configuration: typing.Optional[DetectConfigV2] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[DeidentifyStringResponse]:
+ ) -> AsyncHttpResponse[DeidentifyStringResponseV2]:
"""
- De-identifies sensitive data from a string.
+ De-identifies sensitive data from a string.
Note: V2 API is in beta.
Parameters
----------
text : str
- Text to de-identify.
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyStringRequestEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
+ Text to deidentify.
configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
+ ID of the Detect configuration to use for de-identification.
+
+ configuration : typing.Optional[DetectConfigV2]
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- AsyncHttpResponse[DeidentifyStringResponse]
+ AsyncHttpResponse[DeidentifyStringResponseV2]
OK
"""
_response = await self._client_wrapper.httpx_client.request(
- "v1/detect/deidentify/string",
+ "v2/detect/deidentify/string",
method="POST",
json={
"text": text,
- "vault_id": vault_id,
- "entity_types": entity_types,
- "token_type": convert_and_respect_annotation_metadata(
- object_=token_type, annotation=TokenTypeMapping, direction="write"
- ),
- "allow_regex": allow_regex,
- "restrict_regex": restrict_regex,
- "transformations": convert_and_respect_annotation_metadata(
- object_=transformations, annotation=Transformations, direction="write"
+ "configurationId": configuration_id,
+ "configuration": convert_and_respect_annotation_metadata(
+ object_=configuration, annotation=DetectConfigV2, direction="write"
),
- "configuration_id": configuration_id,
},
headers={
"content-type": "application/json",
@@ -317,9 +276,9 @@ async def deidentify_string(
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- DeidentifyStringResponse,
+ DeidentifyStringResponseV2,
parse_obj_as(
- type_=DeidentifyStringResponse, # type: ignore
+ type_=DeidentifyStringResponseV2, # type: ignore
object_=_response.json(),
),
)
@@ -328,9 +287,9 @@ async def deidentify_string(
raise BadRequestError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -339,9 +298,9 @@ async def deidentify_string(
raise UnauthorizedError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -360,44 +319,51 @@ async def deidentify_string(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
- async def reidentify_string(
+ async def reidentify_string_v2(
self,
*,
- text: typing.Optional[str] = OMIT,
- vault_id: typing.Optional[str] = OMIT,
- format: typing.Optional[Format] = OMIT,
+ vault_id: str,
+ text: str,
+ redaction_level: typing.Optional[typing.Sequence[RedactionLevel]] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[IdentifyResponse]:
+ ) -> AsyncHttpResponse[ReidentifyStringResponseV2]:
"""
- Re-identifies tokens in a string.
+ Re-identifies tokens in a string.
Requires the Detect Invoker, Detect Manager, or Vault Owner role. Re-identifying `vault_token` values also requires a policy that separately grants the Detokenization action, unless the caller has the Vault Owner role.
Note: V2 API is in beta.
Parameters
----------
- text : typing.Optional[str]
- Text to reidentify.
+ vault_id : str
+ ID of the vault used for re-identification. Requires the Detect Invoker, Detect Manager, or Vault Owner role for this vault. Re-identifying `vault_token` values also requires a role or policy that separately grants the Detokenization action, unless the caller has the Vault Owner role.
- vault_id : typing.Optional[str]
- ID of the vault where the entities are stored.
+ text : str
+ Text to reidentify.
- format : typing.Optional[Format]
+ redaction_level : typing.Optional[typing.Sequence[RedactionLevel]]
+ Replacement patterns or types applied to entity types or token groups during re-identification. Specifies a replacement pattern/type and the token group or entity type it applies to during re-identification. Set exactly one of `tokenGroupName` or `entityName`. Use `tokenGroupName` for FlowVault and `entityName` for SkyVault. Similarly, set exactly one of `redactionType` or `redactionPattern` to specify the replacement.
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- AsyncHttpResponse[IdentifyResponse]
+ AsyncHttpResponse[ReidentifyStringResponseV2]
OK
"""
_response = await self._client_wrapper.httpx_client.request(
- "v1/detect/reidentify/string",
+ "v2/detect/reidentify/string",
method="POST",
json={
+ "vaultId": vault_id,
"text": text,
- "vault_id": vault_id,
- "format": convert_and_respect_annotation_metadata(object_=format, annotation=Format, direction="write"),
+ "redactionLevel": convert_and_respect_annotation_metadata(
+ object_=redaction_level, annotation=typing.Sequence[RedactionLevel], direction="write"
+ ),
},
headers={
"content-type": "application/json",
@@ -408,9 +374,9 @@ async def reidentify_string(
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- IdentifyResponse,
+ ReidentifyStringResponseV2,
parse_obj_as(
- type_=IdentifyResponse, # type: ignore
+ type_=ReidentifyStringResponseV2, # type: ignore
object_=_response.json(),
),
)
@@ -419,9 +385,9 @@ async def reidentify_string(
raise BadRequestError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -430,9 +396,9 @@ async def reidentify_string(
raise UnauthorizedError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -451,4 +417,8 @@ async def reidentify_string(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/skyvault/skyflow/generated/rest/guardrails/__init__.py b/common/generated/rest/token_exchange/__init__.py
similarity index 100%
rename from skyvault/skyflow/generated/rest/guardrails/__init__.py
rename to common/generated/rest/token_exchange/__init__.py
diff --git a/common/generated/rest/token_exchange/client.py b/common/generated/rest/token_exchange/client.py
new file mode 100644
index 00000000..b3727f1e
--- /dev/null
+++ b/common/generated/rest/token_exchange/client.py
@@ -0,0 +1,161 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from ..core.request_options import RequestOptions
+from ..types.get_sts_token_response import GetStsTokenResponse
+from .raw_client import AsyncRawTokenExchangeClient, RawTokenExchangeClient
+
+# this is used as the default value for optional parameters
+OMIT = typing.cast(typing.Any, ...)
+
+
+class TokenExchangeClient:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._raw_client = RawTokenExchangeClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> RawTokenExchangeClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawTokenExchangeClient
+ """
+ return self._raw_client
+
+ def get_sts_token(
+ self,
+ *,
+ grant_type: str,
+ subject_token: str,
+ subject_token_type: str,
+ service_account_id: str,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> GetStsTokenResponse:
+ """
+ Generates a Bearer Token to authenticate with Skyflow.
+
+ Parameters
+ ----------
+ grant_type : str
+
+ subject_token : str
+ Subject token.
+
+ subject_token_type : str
+ Subject token type.
+
+ service_account_id : str
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ GetStsTokenResponse
+ OK
+
+ Examples
+ --------
+ from skyflow import SkyflowAuth
+
+ client = SkyflowAuth(
+ token="YOUR_TOKEN",
+ )
+ client.token_exchange.get_sts_token(
+ grant_type="grant_type",
+ subject_token="subject_token",
+ subject_token_type="subject_token_type",
+ service_account_id="service_account_id",
+ )
+ """
+ _response = self._raw_client.get_sts_token(
+ grant_type=grant_type,
+ subject_token=subject_token,
+ subject_token_type=subject_token_type,
+ service_account_id=service_account_id,
+ request_options=request_options,
+ )
+ return _response.data
+
+
+class AsyncTokenExchangeClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawTokenExchangeClient(client_wrapper=client_wrapper)
+
+ @property
+ def with_raw_response(self) -> AsyncRawTokenExchangeClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawTokenExchangeClient
+ """
+ return self._raw_client
+
+ async def get_sts_token(
+ self,
+ *,
+ grant_type: str,
+ subject_token: str,
+ subject_token_type: str,
+ service_account_id: str,
+ request_options: typing.Optional[RequestOptions] = None,
+ ) -> GetStsTokenResponse:
+ """
+ Generates a Bearer Token to authenticate with Skyflow.
+
+ Parameters
+ ----------
+ grant_type : str
+
+ subject_token : str
+ Subject token.
+
+ subject_token_type : str
+ Subject token type.
+
+ service_account_id : str
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ GetStsTokenResponse
+ OK
+
+ Examples
+ --------
+ import asyncio
+
+ from skyflow import AsyncSkyflowAuth
+
+ client = AsyncSkyflowAuth(
+ token="YOUR_TOKEN",
+ )
+
+
+ async def main() -> None:
+ await client.token_exchange.get_sts_token(
+ grant_type="grant_type",
+ subject_token="subject_token",
+ subject_token_type="subject_token_type",
+ service_account_id="service_account_id",
+ )
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.get_sts_token(
+ grant_type=grant_type,
+ subject_token=subject_token,
+ subject_token_type=subject_token_type,
+ service_account_id=service_account_id,
+ request_options=request_options,
+ )
+ return _response.data
diff --git a/skyvault/skyflow/generated/rest/authentication/raw_client.py b/common/generated/rest/token_exchange/raw_client.py
similarity index 54%
rename from skyvault/skyflow/generated/rest/authentication/raw_client.py
rename to common/generated/rest/token_exchange/raw_client.py
index ad2caef6..c6eae1f2 100644
--- a/skyvault/skyflow/generated/rest/authentication/raw_client.py
+++ b/common/generated/rest/token_exchange/raw_client.py
@@ -6,73 +6,65 @@
from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.http_response import AsyncHttpResponse, HttpResponse
+from ..core.parse_error import ParsingError
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
from ..errors.bad_request_error import BadRequestError
+from ..errors.internal_server_error import InternalServerError
from ..errors.not_found_error import NotFoundError
from ..errors.unauthorized_error import UnauthorizedError
-from ..types.v_1_get_auth_token_response import V1GetAuthTokenResponse
+from ..types.error_response import ErrorResponse
+from ..types.get_sts_token_response import GetStsTokenResponse
+from pydantic import ValidationError
# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)
-class RawAuthenticationClient:
+class RawTokenExchangeClient:
def __init__(self, *, client_wrapper: SyncClientWrapper):
self._client_wrapper = client_wrapper
- def authentication_service_get_auth_token(
+ def get_sts_token(
self,
*,
grant_type: str,
- assertion: str,
- subject_token: typing.Optional[str] = OMIT,
- subject_token_type: typing.Optional[str] = OMIT,
- requested_token_use: typing.Optional[str] = OMIT,
- scope: typing.Optional[str] = OMIT,
+ subject_token: str,
+ subject_token_type: str,
+ service_account_id: str,
request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[V1GetAuthTokenResponse]:
+ ) -> HttpResponse[GetStsTokenResponse]:
"""
- Generates a Bearer Token to authenticate with Skyflow. This method doesn't require the Authorization header.
Note: For recommended ways to authenticate, see API authentication.
+ Generates a Bearer Token to authenticate with Skyflow.
Parameters
----------
grant_type : str
- Grant type of the request. Set this to `urn:ietf:params:oauth:grant-type:jwt-bearer`.
- assertion : str
- User-signed JWT token that contains the following fields:
iss: Issuer of the JWT.key: Unique identifier for the key.aud: Recipient the JWT is intended for.exp: Time the JWT expires.sub: Subject of the JWT.ctx: (Optional) Value for Context-aware authorization.
-
- subject_token : typing.Optional[str]
+ subject_token : str
Subject token.
- subject_token_type : typing.Optional[str]
+ subject_token_type : str
Subject token type.
- requested_token_use : typing.Optional[str]
- Token use type. Either `delegation` or `impersonation`.
-
- scope : typing.Optional[str]
- Subset of available roles to associate with the requested token. Uses the format "role:\ role:\".
+ service_account_id : str
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- HttpResponse[V1GetAuthTokenResponse]
- A successful response.
+ HttpResponse[GetStsTokenResponse]
+ OK
"""
_response = self._client_wrapper.httpx_client.request(
- "v1/auth/sa/oauth/token",
+ "v1/auth/sts/token",
method="POST",
json={
"grant_type": grant_type,
- "assertion": assertion,
"subject_token": subject_token,
"subject_token_type": subject_token_type,
- "requested_token_use": requested_token_use,
- "scope": scope,
+ "service_account_id": service_account_id,
},
headers={
"content-type": "application/json",
@@ -83,9 +75,9 @@ def authentication_service_get_auth_token(
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- V1GetAuthTokenResponse,
+ GetStsTokenResponse,
parse_obj_as(
- type_=V1GetAuthTokenResponse, # type: ignore
+ type_=GetStsTokenResponse, # type: ignore
object_=_response.json(),
),
)
@@ -94,9 +86,9 @@ def authentication_service_get_auth_token(
raise BadRequestError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -105,9 +97,9 @@ def authentication_service_get_auth_token(
raise UnauthorizedError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -116,9 +108,20 @@ def authentication_service_get_auth_token(
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 500:
+ raise InternalServerError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -126,65 +129,57 @@ def authentication_service_get_auth_token(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-class AsyncRawAuthenticationClient:
+class AsyncRawTokenExchangeClient:
def __init__(self, *, client_wrapper: AsyncClientWrapper):
self._client_wrapper = client_wrapper
- async def authentication_service_get_auth_token(
+ async def get_sts_token(
self,
*,
grant_type: str,
- assertion: str,
- subject_token: typing.Optional[str] = OMIT,
- subject_token_type: typing.Optional[str] = OMIT,
- requested_token_use: typing.Optional[str] = OMIT,
- scope: typing.Optional[str] = OMIT,
+ subject_token: str,
+ subject_token_type: str,
+ service_account_id: str,
request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[V1GetAuthTokenResponse]:
+ ) -> AsyncHttpResponse[GetStsTokenResponse]:
"""
- Generates a Bearer Token to authenticate with Skyflow. This method doesn't require the Authorization header.
Note: For recommended ways to authenticate, see API authentication.
+ Generates a Bearer Token to authenticate with Skyflow.
Parameters
----------
grant_type : str
- Grant type of the request. Set this to `urn:ietf:params:oauth:grant-type:jwt-bearer`.
- assertion : str
- User-signed JWT token that contains the following fields:
iss: Issuer of the JWT.key: Unique identifier for the key.aud: Recipient the JWT is intended for.exp: Time the JWT expires.sub: Subject of the JWT.ctx: (Optional) Value for Context-aware authorization.
-
- subject_token : typing.Optional[str]
+ subject_token : str
Subject token.
- subject_token_type : typing.Optional[str]
+ subject_token_type : str
Subject token type.
- requested_token_use : typing.Optional[str]
- Token use type. Either `delegation` or `impersonation`.
-
- scope : typing.Optional[str]
- Subset of available roles to associate with the requested token. Uses the format "role:\ role:\".
+ service_account_id : str
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- AsyncHttpResponse[V1GetAuthTokenResponse]
- A successful response.
+ AsyncHttpResponse[GetStsTokenResponse]
+ OK
"""
_response = await self._client_wrapper.httpx_client.request(
- "v1/auth/sa/oauth/token",
+ "v1/auth/sts/token",
method="POST",
json={
"grant_type": grant_type,
- "assertion": assertion,
"subject_token": subject_token,
"subject_token_type": subject_token_type,
- "requested_token_use": requested_token_use,
- "scope": scope,
+ "service_account_id": service_account_id,
},
headers={
"content-type": "application/json",
@@ -195,9 +190,9 @@ async def authentication_service_get_auth_token(
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- V1GetAuthTokenResponse,
+ GetStsTokenResponse,
parse_obj_as(
- type_=V1GetAuthTokenResponse, # type: ignore
+ type_=GetStsTokenResponse, # type: ignore
object_=_response.json(),
),
)
@@ -206,9 +201,9 @@ async def authentication_service_get_auth_token(
raise BadRequestError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -217,9 +212,9 @@ async def authentication_service_get_auth_token(
raise UnauthorizedError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -228,9 +223,20 @@ async def authentication_service_get_auth_token(
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 500:
+ raise InternalServerError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -238,4 +244,8 @@ async def authentication_service_get_auth_token(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/common/generated/rest/types/__init__.py b/common/generated/rest/types/__init__.py
index 8a9140f5..af32a062 100644
--- a/common/generated/rest/types/__init__.py
+++ b/common/generated/rest/types/__init__.py
@@ -2,8 +2,187 @@
# isort: skip_file
-from .googlerpc_status import GooglerpcStatus
-from .protobuf_any import ProtobufAny
-from .v_1_get_auth_token_response import V1GetAuthTokenResponse
+import typing
+from importlib import import_module
-__all__ = ["GooglerpcStatus", "ProtobufAny", "V1GetAuthTokenResponse"]
+if typing.TYPE_CHECKING:
+ from .audio_v2 import AudioV2
+ from .audio_v2bleep import AudioV2Bleep
+ from .audio_v2output_transcription import AudioV2OutputTranscription
+ from .deidentify_file_response_v2 import DeidentifyFileResponseV2
+ from .deidentify_string_response_v2 import DeidentifyStringResponseV2
+ from .deidentify_string_response_v2detected_entity import DeidentifyStringResponseV2DetectedEntity
+ from .deidentify_string_response_v2entity_location import DeidentifyStringResponseV2EntityLocation
+ from .detect import Detect
+ from .detect_config_v2 import DetectConfigV2
+ from .detect_config_v2vault_type import DetectConfigV2VaultType
+ from .detect_custom_types import DetectCustomTypes
+ from .detect_custom_types_deidentification_type import DetectCustomTypesDeidentificationType
+ from .detect_custom_types_include_prefix import DetectCustomTypesIncludePrefix
+ from .detect_entity import DetectEntity
+ from .detect_entity_deidentification_type import DetectEntityDeidentificationType
+ from .detect_entity_entity_type import DetectEntityEntityType
+ from .detect_entity_include_prefix import DetectEntityIncludePrefix
+ from .detect_guardrails_response_v2 import DetectGuardrailsResponseV2
+ from .detect_guardrails_response_v2validation import DetectGuardrailsResponseV2Validation
+ from .detect_object_entity import DetectObjectEntity
+ from .detect_object_entity_deidentification_type import DetectObjectEntityDeidentificationType
+ from .detect_object_entity_entity_type import DetectObjectEntityEntityType
+ from .detect_return_entities import DetectReturnEntities
+ from .detect_runs_response_v2 import DetectRunsResponseV2
+ from .detect_runs_response_v2output_type import DetectRunsResponseV2OutputType
+ from .detect_runs_response_v2status import DetectRunsResponseV2Status
+ from .document_v2 import DocumentV2
+ from .document_v2pdf import DocumentV2Pdf
+ from .document_v2pdf_processing_mode import DocumentV2PdfProcessingMode
+ from .entity_transformation import EntityTransformation
+ from .error_response import ErrorResponse
+ from .error_response_error import ErrorResponseError
+ from .file_mapping import FileMapping
+ from .file_output import FileOutput
+ from .file_output_processed_file_extension import FileOutputProcessedFileExtension
+ from .file_output_processed_file_type import FileOutputProcessedFileType
+ from .get_auth_token_response import GetAuthTokenResponse
+ from .get_sts_token_response import GetStsTokenResponse
+ from .http_code import HttpCode
+ from .image_v2 import ImageV2
+ from .image_v2masking_method import ImageV2MaskingMethod
+ from .media import Media
+ from .metrics import Metrics
+ from .redaction_level import RedactionLevel
+ from .redaction_level_entity_name import RedactionLevelEntityName
+ from .redaction_level_redaction_type import RedactionLevelRedactionType
+ from .reidentify_file_response_v2 import ReidentifyFileResponseV2
+ from .reidentify_file_response_v2output_type import ReidentifyFileResponseV2OutputType
+ from .reidentify_file_response_v2status import ReidentifyFileResponseV2Status
+ from .reidentify_string_response_v2 import ReidentifyStringResponseV2
+ from .transformation_shift_dates import TransformationShiftDates
+_dynamic_imports: typing.Dict[str, str] = {
+ "AudioV2": ".audio_v2",
+ "AudioV2Bleep": ".audio_v2bleep",
+ "AudioV2OutputTranscription": ".audio_v2output_transcription",
+ "DeidentifyFileResponseV2": ".deidentify_file_response_v2",
+ "DeidentifyStringResponseV2": ".deidentify_string_response_v2",
+ "DeidentifyStringResponseV2DetectedEntity": ".deidentify_string_response_v2detected_entity",
+ "DeidentifyStringResponseV2EntityLocation": ".deidentify_string_response_v2entity_location",
+ "Detect": ".detect",
+ "DetectConfigV2": ".detect_config_v2",
+ "DetectConfigV2VaultType": ".detect_config_v2vault_type",
+ "DetectCustomTypes": ".detect_custom_types",
+ "DetectCustomTypesDeidentificationType": ".detect_custom_types_deidentification_type",
+ "DetectCustomTypesIncludePrefix": ".detect_custom_types_include_prefix",
+ "DetectEntity": ".detect_entity",
+ "DetectEntityDeidentificationType": ".detect_entity_deidentification_type",
+ "DetectEntityEntityType": ".detect_entity_entity_type",
+ "DetectEntityIncludePrefix": ".detect_entity_include_prefix",
+ "DetectGuardrailsResponseV2": ".detect_guardrails_response_v2",
+ "DetectGuardrailsResponseV2Validation": ".detect_guardrails_response_v2validation",
+ "DetectObjectEntity": ".detect_object_entity",
+ "DetectObjectEntityDeidentificationType": ".detect_object_entity_deidentification_type",
+ "DetectObjectEntityEntityType": ".detect_object_entity_entity_type",
+ "DetectReturnEntities": ".detect_return_entities",
+ "DetectRunsResponseV2": ".detect_runs_response_v2",
+ "DetectRunsResponseV2OutputType": ".detect_runs_response_v2output_type",
+ "DetectRunsResponseV2Status": ".detect_runs_response_v2status",
+ "DocumentV2": ".document_v2",
+ "DocumentV2Pdf": ".document_v2pdf",
+ "DocumentV2PdfProcessingMode": ".document_v2pdf_processing_mode",
+ "EntityTransformation": ".entity_transformation",
+ "ErrorResponse": ".error_response",
+ "ErrorResponseError": ".error_response_error",
+ "FileMapping": ".file_mapping",
+ "FileOutput": ".file_output",
+ "FileOutputProcessedFileExtension": ".file_output_processed_file_extension",
+ "FileOutputProcessedFileType": ".file_output_processed_file_type",
+ "GetAuthTokenResponse": ".get_auth_token_response",
+ "GetStsTokenResponse": ".get_sts_token_response",
+ "HttpCode": ".http_code",
+ "ImageV2": ".image_v2",
+ "ImageV2MaskingMethod": ".image_v2masking_method",
+ "Media": ".media",
+ "Metrics": ".metrics",
+ "RedactionLevel": ".redaction_level",
+ "RedactionLevelEntityName": ".redaction_level_entity_name",
+ "RedactionLevelRedactionType": ".redaction_level_redaction_type",
+ "ReidentifyFileResponseV2": ".reidentify_file_response_v2",
+ "ReidentifyFileResponseV2OutputType": ".reidentify_file_response_v2output_type",
+ "ReidentifyFileResponseV2Status": ".reidentify_file_response_v2status",
+ "ReidentifyStringResponseV2": ".reidentify_string_response_v2",
+ "TransformationShiftDates": ".transformation_shift_dates",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = [
+ "AudioV2",
+ "AudioV2Bleep",
+ "AudioV2OutputTranscription",
+ "DeidentifyFileResponseV2",
+ "DeidentifyStringResponseV2",
+ "DeidentifyStringResponseV2DetectedEntity",
+ "DeidentifyStringResponseV2EntityLocation",
+ "Detect",
+ "DetectConfigV2",
+ "DetectConfigV2VaultType",
+ "DetectCustomTypes",
+ "DetectCustomTypesDeidentificationType",
+ "DetectCustomTypesIncludePrefix",
+ "DetectEntity",
+ "DetectEntityDeidentificationType",
+ "DetectEntityEntityType",
+ "DetectEntityIncludePrefix",
+ "DetectGuardrailsResponseV2",
+ "DetectGuardrailsResponseV2Validation",
+ "DetectObjectEntity",
+ "DetectObjectEntityDeidentificationType",
+ "DetectObjectEntityEntityType",
+ "DetectReturnEntities",
+ "DetectRunsResponseV2",
+ "DetectRunsResponseV2OutputType",
+ "DetectRunsResponseV2Status",
+ "DocumentV2",
+ "DocumentV2Pdf",
+ "DocumentV2PdfProcessingMode",
+ "EntityTransformation",
+ "ErrorResponse",
+ "ErrorResponseError",
+ "FileMapping",
+ "FileOutput",
+ "FileOutputProcessedFileExtension",
+ "FileOutputProcessedFileType",
+ "GetAuthTokenResponse",
+ "GetStsTokenResponse",
+ "HttpCode",
+ "ImageV2",
+ "ImageV2MaskingMethod",
+ "Media",
+ "Metrics",
+ "RedactionLevel",
+ "RedactionLevelEntityName",
+ "RedactionLevelRedactionType",
+ "ReidentifyFileResponseV2",
+ "ReidentifyFileResponseV2OutputType",
+ "ReidentifyFileResponseV2Status",
+ "ReidentifyStringResponseV2",
+ "TransformationShiftDates",
+]
diff --git a/common/generated/rest/types/audio_v2.py b/common/generated/rest/types/audio_v2.py
new file mode 100644
index 00000000..b0bab0cc
--- /dev/null
+++ b/common/generated/rest/types/audio_v2.py
@@ -0,0 +1,51 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+import typing_extensions
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from ..core.serialization import FieldMetadata
+from .audio_v2bleep import AudioV2Bleep
+from .audio_v2output_transcription import AudioV2OutputTranscription
+
+
+class AudioV2(UniversalBaseModel):
+ """
+ Audio detection and deidentification configuration.
+ """
+
+ output_processed_audio: typing_extensions.Annotated[
+ typing.Optional[bool],
+ FieldMetadata(alias="outputProcessedAudio"),
+ pydantic.Field(
+ alias="outputProcessedAudio",
+ description="If `true`, includes processed audio file in the response. Can't be used together with `outputTranscription`.",
+ ),
+ ] = None
+ """
+ If `true`, includes processed audio file in the response. Can't be used together with `outputTranscription`.
+ """
+
+ output_transcription: typing_extensions.Annotated[
+ typing.Optional[AudioV2OutputTranscription],
+ FieldMetadata(alias="outputTranscription"),
+ pydantic.Field(
+ alias="outputTranscription",
+ description="Type of transcription to include in the response. `TRANSCRIPTION`: standard transcript of the audio. `MEDICAL_TRANSCRIPTION`: transcript focused on medical content and terminology. `DIARIZED_TRANSCRIPTION`: speaker-separated transcript that labels each speaker's dialogue. `MEDICAL_DIARIZED_TRANSCRIPTION`: speaker-separated transcript focused on medical content and terminology. `NONE`: no transcription is included. Can't be used together with `outputProcessedAudio`.",
+ ),
+ ] = None
+ """
+ Type of transcription to include in the response. `TRANSCRIPTION`: standard transcript of the audio. `MEDICAL_TRANSCRIPTION`: transcript focused on medical content and terminology. `DIARIZED_TRANSCRIPTION`: speaker-separated transcript that labels each speaker's dialogue. `MEDICAL_DIARIZED_TRANSCRIPTION`: speaker-separated transcript focused on medical content and terminology. `NONE`: no transcription is included. Can't be used together with `outputProcessedAudio`.
+ """
+
+ bleep: typing.Optional[AudioV2Bleep] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/common/generated/rest/types/audio_v2bleep.py b/common/generated/rest/types/audio_v2bleep.py
new file mode 100644
index 00000000..64f2e539
--- /dev/null
+++ b/common/generated/rest/types/audio_v2bleep.py
@@ -0,0 +1,57 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+import typing_extensions
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from ..core.serialization import FieldMetadata
+
+
+class AudioV2Bleep(UniversalBaseModel):
+ """
+ Configuration for the bleep sound used to mask detected entities in audio.
+ """
+
+ start_padding: typing_extensions.Annotated[
+ typing.Optional[float],
+ FieldMetadata(alias="startPadding"),
+ pydantic.Field(
+ alias="startPadding",
+ description="Padding added to the beginning of a bleep, in seconds. Range: 0–20. Defaults to 0.5.",
+ ),
+ ] = None
+ """
+ Padding added to the beginning of a bleep, in seconds. Range: 0–20. Defaults to 0.5.
+ """
+
+ stop_padding: typing_extensions.Annotated[
+ typing.Optional[float],
+ FieldMetadata(alias="stopPadding"),
+ pydantic.Field(
+ alias="stopPadding",
+ description="Padding added to the end of a bleep, in seconds. Range: 0–20. Defaults to 0.2.",
+ ),
+ ] = None
+ """
+ Padding added to the end of a bleep, in seconds. Range: 0–20. Defaults to 0.2.
+ """
+
+ frequency: typing.Optional[int] = pydantic.Field(default=None)
+ """
+ Frequency of the sine wave used for the bleep sound, in Hz.
+ """
+
+ gain: typing.Optional[int] = pydantic.Field(default=None)
+ """
+ Relative loudness of the bleep. Positive values increase loudness and negative values decrease it.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/common/generated/rest/types/audio_v2output_transcription.py b/common/generated/rest/types/audio_v2output_transcription.py
new file mode 100644
index 00000000..601968f8
--- /dev/null
+++ b/common/generated/rest/types/audio_v2output_transcription.py
@@ -0,0 +1,10 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+AudioV2OutputTranscription = typing.Union[
+ typing.Literal[
+ "NONE", "TRANSCRIPTION", "MEDICAL_TRANSCRIPTION", "DIARIZED_TRANSCRIPTION", "MEDICAL_DIARIZED_TRANSCRIPTION"
+ ],
+ typing.Any,
+]
diff --git a/skyvault/skyflow/generated/rest/types/file_data_deidentify_pdf.py b/common/generated/rest/types/deidentify_file_response_v2.py
similarity index 59%
rename from skyvault/skyflow/generated/rest/types/file_data_deidentify_pdf.py
rename to common/generated/rest/types/deidentify_file_response_v2.py
index 0dc2c1a5..1ad88509 100644
--- a/skyvault/skyflow/generated/rest/types/file_data_deidentify_pdf.py
+++ b/common/generated/rest/types/deidentify_file_response_v2.py
@@ -8,19 +8,18 @@
from ..core.serialization import FieldMetadata
-class FileDataDeidentifyPdf(UniversalBaseModel):
+class DeidentifyFileResponseV2(UniversalBaseModel):
"""
- File to process. Files are specified as Base64-encoded data.
+ Response containing the run ID for tracking the async deidentification job.
"""
- base_64: typing_extensions.Annotated[str, FieldMetadata(alias="base64")] = pydantic.Field()
+ run_id: typing_extensions.Annotated[
+ typing.Optional[str],
+ FieldMetadata(alias="runId"),
+ pydantic.Field(alias="runId", description="Run ID of the deidentification request."),
+ ] = None
"""
- Base64-encoded data of the file.
- """
-
- data_format: typing.Literal["pdf"] = pydantic.Field(default="pdf")
- """
- Format of the file.
+ Run ID of the deidentification request.
"""
if IS_PYDANTIC_V2:
diff --git a/common/generated/rest/types/deidentify_string_response_v2.py b/common/generated/rest/types/deidentify_string_response_v2.py
new file mode 100644
index 00000000..c484a6f5
--- /dev/null
+++ b/common/generated/rest/types/deidentify_string_response_v2.py
@@ -0,0 +1,41 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+import typing_extensions
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from ..core.serialization import FieldMetadata
+from .deidentify_string_response_v2detected_entity import DeidentifyStringResponseV2DetectedEntity
+from .metrics import Metrics
+
+
+class DeidentifyStringResponseV2(UniversalBaseModel):
+ """
+ Response containing the deidentified string and detected entity metadata.
+ """
+
+ processed_text: typing_extensions.Annotated[
+ typing.Optional[str],
+ FieldMetadata(alias="processedText"),
+ pydantic.Field(alias="processedText", description="Deidentified text with sensitive entities replaced."),
+ ] = None
+ """
+ Deidentified text with sensitive entities replaced.
+ """
+
+ entities: typing.Optional[typing.List[DeidentifyStringResponseV2DetectedEntity]] = pydantic.Field(default=None)
+ """
+ Detected entities.
+ """
+
+ metrics: typing.Optional[Metrics] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/string_response_entities.py b/common/generated/rest/types/deidentify_string_response_v2detected_entity.py
similarity index 51%
rename from skyvault/skyflow/generated/rest/types/string_response_entities.py
rename to common/generated/rest/types/deidentify_string_response_v2detected_entity.py
index 864d5a46..cb1a207f 100644
--- a/skyvault/skyflow/generated/rest/types/string_response_entities.py
+++ b/common/generated/rest/types/deidentify_string_response_v2detected_entity.py
@@ -3,11 +3,13 @@
import typing
import pydantic
+import typing_extensions
from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from .locations import Locations
+from ..core.serialization import FieldMetadata
+from .deidentify_string_response_v2entity_location import DeidentifyStringResponseV2EntityLocation
-class StringResponseEntities(UniversalBaseModel):
+class DeidentifyStringResponseV2DetectedEntity(UniversalBaseModel):
"""
Detected entities for String
"""
@@ -22,13 +24,21 @@ class StringResponseEntities(UniversalBaseModel):
Original text of the entity.
"""
- location: typing.Optional[Locations] = None
- entity_type: typing.Optional[str] = pydantic.Field(default=None)
+ location: typing.Optional[DeidentifyStringResponseV2EntityLocation] = None
+ entity_type: typing_extensions.Annotated[
+ typing.Optional[str],
+ FieldMetadata(alias="entityType"),
+ pydantic.Field(alias="entityType", description="Highest-rated label."),
+ ] = None
"""
Highest-rated label.
"""
- entity_scores: typing.Optional[typing.Dict[str, float]] = pydantic.Field(default=None)
+ entity_scores: typing_extensions.Annotated[
+ typing.Optional[typing.Dict[str, float]],
+ FieldMetadata(alias="entityScores"),
+ pydantic.Field(alias="entityScores", description="Labels and their scores."),
+ ] = None
"""
Labels and their scores.
"""
diff --git a/common/generated/rest/types/deidentify_string_response_v2entity_location.py b/common/generated/rest/types/deidentify_string_response_v2entity_location.py
new file mode 100644
index 00000000..9d137e81
--- /dev/null
+++ b/common/generated/rest/types/deidentify_string_response_v2entity_location.py
@@ -0,0 +1,65 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+import typing_extensions
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from ..core.serialization import FieldMetadata
+
+
+class DeidentifyStringResponseV2EntityLocation(UniversalBaseModel):
+ """
+ Locations of an entity in the text.
+ """
+
+ start_index: typing_extensions.Annotated[
+ typing.Optional[int],
+ FieldMetadata(alias="startIndex"),
+ pydantic.Field(
+ alias="startIndex", description="Index of the first character of the string in the original text."
+ ),
+ ] = None
+ """
+ Index of the first character of the string in the original text.
+ """
+
+ end_index: typing_extensions.Annotated[
+ typing.Optional[int],
+ FieldMetadata(alias="endIndex"),
+ pydantic.Field(alias="endIndex", description="Index of the last character of the string in the original text."),
+ ] = None
+ """
+ Index of the last character of the string in the original text.
+ """
+
+ start_index_processed: typing_extensions.Annotated[
+ typing.Optional[int],
+ FieldMetadata(alias="startIndexProcessed"),
+ pydantic.Field(
+ alias="startIndexProcessed", description="Index of the first character of the string in the processed text."
+ ),
+ ] = None
+ """
+ Index of the first character of the string in the processed text.
+ """
+
+ end_index_processed: typing_extensions.Annotated[
+ typing.Optional[int],
+ FieldMetadata(alias="endIndexProcessed"),
+ pydantic.Field(
+ alias="endIndexProcessed", description="Index of the last character of the string in the processed text."
+ ),
+ ] = None
+ """
+ Index of the last character of the string in the processed text.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/common/generated/rest/types/detect.py b/common/generated/rest/types/detect.py
new file mode 100644
index 00000000..7b494b72
--- /dev/null
+++ b/common/generated/rest/types/detect.py
@@ -0,0 +1,72 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+import typing_extensions
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from ..core.serialization import FieldMetadata
+from .detect_custom_types import DetectCustomTypes
+from .detect_entity import DetectEntity
+from .detect_object_entity import DetectObjectEntity
+from .detect_return_entities import DetectReturnEntities
+
+
+class Detect(UniversalBaseModel):
+ """
+ Entity detection and deidentification settings.
+ """
+
+ entities: typing.Optional[typing.List[DetectEntity]] = pydantic.Field(default=None)
+ """
+ Entities and their deidentification settings.
+ """
+
+ object_entities: typing_extensions.Annotated[
+ typing.Optional[typing.List[DetectObjectEntity]],
+ FieldMetadata(alias="objectEntities"),
+ pydantic.Field(alias="objectEntities", description="Object entities and their deidentification settings."),
+ ] = None
+ """
+ Object entities and their deidentification settings.
+ """
+
+ restrict: typing.Optional[typing.List[str]] = pydantic.Field(default=None)
+ """
+ Settings for restricting detected entities. A detected entity is replaced with '[RESTRICTED]' only when a `restrict` pattern matches the entity's full value. If a pattern matches only a substring of the detected entity, the pattern is ignored and the entity is processed according to the configured tokenization and transformation settings. Patterns don't match across entity boundaries. If an entity matches both a `skip` and a `restrict` pattern, `skip` takes precedence and the entity is displayed in plaintext. Note: Vault tokens are currently not supported.
+ """
+
+ skip: typing.Optional[typing.List[str]] = pydantic.Field(default=None)
+ """
+ Settings for bypassing deidentification on detected entities. A detected entity is displayed in plaintext when a `skip` pattern matches either the entity's full value or any substring of it. Patterns don't match across entity boundaries. If an entity matches both a `skip` and a `restrict` pattern, `skip` takes precedence and the entity is displayed in plaintext.
+ """
+
+ custom_types: typing_extensions.Annotated[
+ typing.Optional[typing.List[DetectCustomTypes]],
+ FieldMetadata(alias="customTypes"),
+ pydantic.Field(alias="customTypes", description="Custom entity type definitions."),
+ ] = None
+ """
+ Custom entity type definitions.
+ """
+
+ return_entities: typing_extensions.Annotated[
+ typing.Optional[DetectReturnEntities],
+ FieldMetadata(alias="returnEntities"),
+ pydantic.Field(
+ alias="returnEntities",
+ description="Controls which detected entities are returned in the response. `EXCLUDE_SENSITIVE_DATA`: returns each detected entity's metadata (token, entity type, location, and confidence scores) but omits the original sensitive value. `ALL`: returns each detected entity's metadata and the original sensitive value. `NONE`: doesn't return detected entities.",
+ ),
+ ] = None
+ """
+ Controls which detected entities are returned in the response. `EXCLUDE_SENSITIVE_DATA`: returns each detected entity's metadata (token, entity type, location, and confidence scores) but omits the original sensitive value. `ALL`: returns each detected entity's metadata and the original sensitive value. `NONE`: doesn't return detected entities.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/common/generated/rest/types/detect_config_v2.py b/common/generated/rest/types/detect_config_v2.py
new file mode 100644
index 00000000..20007637
--- /dev/null
+++ b/common/generated/rest/types/detect_config_v2.py
@@ -0,0 +1,79 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+import typing_extensions
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from ..core.serialization import FieldMetadata
+from .detect import Detect
+from .detect_config_v2vault_type import DetectConfigV2VaultType
+from .file_mapping import FileMapping
+from .media import Media
+
+
+class DetectConfigV2(UniversalBaseModel):
+ """
+ Configuration for detecting and deidentifying entities in a vault.
+ """
+
+ id: typing_extensions.Annotated[
+ typing.Optional[str],
+ FieldMetadata(alias="ID"),
+ pydantic.Field(alias="ID", description="ID of the configuration."),
+ ] = None
+ """
+ ID of the configuration.
+ """
+
+ name: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Name of the configuration.
+ """
+
+ namespace: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Namespace of the configuration.
+ """
+
+ description: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Description of the configuration.
+ """
+
+ vault_id: typing_extensions.Annotated[
+ str, FieldMetadata(alias="vaultId"), pydantic.Field(alias="vaultId", description="ID of the vault.")
+ ]
+ """
+ ID of the vault.
+ """
+
+ vault_type: typing_extensions.Annotated[
+ typing.Optional[DetectConfigV2VaultType],
+ FieldMetadata(alias="vaultType"),
+ pydantic.Field(alias="vaultType", description="Type of the vault."),
+ ] = None
+ """
+ Type of the vault.
+ """
+
+ detect: typing.Optional[Detect] = None
+ file_mapping: typing_extensions.Annotated[
+ typing.Optional[typing.List[FileMapping]],
+ FieldMetadata(alias="fileMapping"),
+ pydantic.Field(alias="fileMapping", description="Mappings for source and deidentified file locations."),
+ ] = None
+ """
+ Mappings for source and deidentified file locations.
+ """
+
+ media: typing.Optional[Media] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/common/generated/rest/types/detect_config_v2vault_type.py b/common/generated/rest/types/detect_config_v2vault_type.py
new file mode 100644
index 00000000..faa1a618
--- /dev/null
+++ b/common/generated/rest/types/detect_config_v2vault_type.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+DetectConfigV2VaultType = typing.Union[typing.Literal["NONE", "PRIVACYDB", "FLOWDB", "FLOWDB_SCHEMALESS"], typing.Any]
diff --git a/common/generated/rest/types/detect_custom_types.py b/common/generated/rest/types/detect_custom_types.py
new file mode 100644
index 00000000..9ea0caeb
--- /dev/null
+++ b/common/generated/rest/types/detect_custom_types.py
@@ -0,0 +1,76 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+import typing_extensions
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from ..core.serialization import FieldMetadata
+from .detect_custom_types_deidentification_type import DetectCustomTypesDeidentificationType
+from .detect_custom_types_include_prefix import DetectCustomTypesIncludePrefix
+
+
+class DetectCustomTypes(UniversalBaseModel):
+ """
+ Custom entity type defined by a label and a list of match values.
+ """
+
+ label: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Label of the custom type. Used as the entity's identity and default token prefix.
+ """
+
+ match: typing.Optional[typing.List[str]] = pydantic.Field(default=None)
+ """
+ Regular expressions to replace with '[]' enclosed in square brackets. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be redacted. Expressions don't match across entity boundaries. If a string or entity matches both `skip` and `customType.label`, the entity is displayed in plaintext. If a string is detected as an entity and a `customType.match` pattern matches the entire detected entity, the entity is replaced with '[]'. If a string is detected as an entity but a `customType.match` pattern only matches a substring of it, the `customType.match` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
+ """
+
+ deidentification_type: typing_extensions.Annotated[
+ typing.Optional[DetectCustomTypesDeidentificationType],
+ FieldMetadata(alias="deidentificationType"),
+ pydantic.Field(
+ alias="deidentificationType",
+ description="Type of deidentification to apply to matches of this custom type.",
+ ),
+ ] = None
+ """
+ Type of deidentification to apply to matches of this custom type.
+ """
+
+ destination: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Vault destination where matches of this custom type are stored. Required when `deidentificationType` is `VAULT_TOKEN`. For vaults with a schema, specify the table and column in `table.column` format (for example, `persons.product`). For schemaless vaults, specify the token group name (for example, `productTokenGroup`).
+ """
+
+ include_prefix: typing_extensions.Annotated[
+ typing.Optional[DetectCustomTypesIncludePrefix],
+ FieldMetadata(alias="includePrefix"),
+ pydantic.Field(
+ alias="includePrefix",
+ description="Whether to include the label as a prefix in the generated token. Only applies when `deidentificationType` is `VAULT_TOKEN`. `NO` returns the raw vault token, and the value can't be re-identified later.",
+ ),
+ ] = None
+ """
+ Whether to include the label as a prefix in the generated token. Only applies when `deidentificationType` is `VAULT_TOKEN`. `NO` returns the raw vault token, and the value can't be re-identified later.
+ """
+
+ prefix_override: typing_extensions.Annotated[
+ typing.Optional[str],
+ FieldMetadata(alias="prefixOverride"),
+ pydantic.Field(
+ alias="prefixOverride",
+ description="Overrides the default entity-type prefix used in the generated token (for example, `NAAM` instead of `NAME`, producing `[NAAM_]`). Can't be combined with `includePrefix: NO`.",
+ ),
+ ] = None
+ """
+ Overrides the default entity-type prefix used in the generated token (for example, `NAAM` instead of `NAME`, producing `[NAAM_]`). Can't be combined with `includePrefix: NO`.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/common/generated/rest/types/detect_custom_types_deidentification_type.py b/common/generated/rest/types/detect_custom_types_deidentification_type.py
new file mode 100644
index 00000000..1398d323
--- /dev/null
+++ b/common/generated/rest/types/detect_custom_types_deidentification_type.py
@@ -0,0 +1,7 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+DetectCustomTypesDeidentificationType = typing.Union[
+ typing.Literal["UNKNOWN", "ENTITY_UNIQUE_COUNTER", "ENTITY_ONLY", "VAULT_TOKEN", "MASK"], typing.Any
+]
diff --git a/common/generated/rest/types/detect_custom_types_include_prefix.py b/common/generated/rest/types/detect_custom_types_include_prefix.py
new file mode 100644
index 00000000..a8b46c64
--- /dev/null
+++ b/common/generated/rest/types/detect_custom_types_include_prefix.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+DetectCustomTypesIncludePrefix = typing.Union[typing.Literal["YES", "NO"], typing.Any]
diff --git a/common/generated/rest/types/detect_entity.py b/common/generated/rest/types/detect_entity.py
new file mode 100644
index 00000000..5eb46ce6
--- /dev/null
+++ b/common/generated/rest/types/detect_entity.py
@@ -0,0 +1,78 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+import typing_extensions
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from ..core.serialization import FieldMetadata
+from .detect_entity_deidentification_type import DetectEntityDeidentificationType
+from .detect_entity_entity_type import DetectEntityEntityType
+from .detect_entity_include_prefix import DetectEntityIncludePrefix
+from .entity_transformation import EntityTransformation
+
+
+class DetectEntity(UniversalBaseModel):
+ """
+ Entity detection and deidentification configuration.
+ """
+
+ entity_type: typing_extensions.Annotated[
+ typing.Optional[DetectEntityEntityType],
+ FieldMetadata(alias="entityType"),
+ pydantic.Field(alias="entityType", description="Type of entity to detect."),
+ ] = None
+ """
+ Type of entity to detect.
+ """
+
+ deidentification_type: typing_extensions.Annotated[
+ typing.Optional[DetectEntityDeidentificationType],
+ FieldMetadata(alias="deidentificationType"),
+ pydantic.Field(
+ alias="deidentificationType",
+ description="Type of deidentification to apply. `VAULT_TOKEN` is only supported for the following file formats: `txt`, `json`, `csv`, `xml`, `jsonl`, `docx`, `xlsx`, `pptx`.",
+ ),
+ ] = None
+ """
+ Type of deidentification to apply. `VAULT_TOKEN` is only supported for the following file formats: `txt`, `json`, `csv`, `xml`, `jsonl`, `docx`, `xlsx`, `pptx`.
+ """
+
+ destination: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Vault destination where detected values of this entity type are stored. For vaults with a schema, specify the table and column in `table.column` format (for example, `persons.name`). For schemaless vaults, specify the token group name (for example, `personTokenGroup`).
+ """
+
+ transformation: typing.Optional[EntityTransformation] = None
+ include_prefix: typing_extensions.Annotated[
+ typing.Optional[DetectEntityIncludePrefix],
+ FieldMetadata(alias="includePrefix"),
+ pydantic.Field(
+ alias="includePrefix",
+ description="Whether to include the label as a prefix in the generated token. Only applies when `deidentificationType` is `VAULT_TOKEN`. `NO` returns the raw vault token, and the value can't be re-identified later.",
+ ),
+ ] = None
+ """
+ Whether to include the label as a prefix in the generated token. Only applies when `deidentificationType` is `VAULT_TOKEN`. `NO` returns the raw vault token, and the value can't be re-identified later.
+ """
+
+ prefix_override: typing_extensions.Annotated[
+ typing.Optional[str],
+ FieldMetadata(alias="prefixOverride"),
+ pydantic.Field(
+ alias="prefixOverride",
+ description="Overrides the default entity-type prefix used in the generated token (for example, `NAAM` instead of `NAME`, producing `[NAAM_]`). Can't be combined with `includePrefix: NO`.",
+ ),
+ ] = None
+ """
+ Overrides the default entity-type prefix used in the generated token (for example, `NAAM` instead of `NAME`, producing `[NAAM_]`). Can't be combined with `includePrefix: NO`.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/common/generated/rest/types/detect_entity_deidentification_type.py b/common/generated/rest/types/detect_entity_deidentification_type.py
new file mode 100644
index 00000000..1673101d
--- /dev/null
+++ b/common/generated/rest/types/detect_entity_deidentification_type.py
@@ -0,0 +1,7 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+DetectEntityDeidentificationType = typing.Union[
+ typing.Literal["UNKNOWN", "ENTITY_UNIQUE_COUNTER", "ENTITY_ONLY", "VAULT_TOKEN", "MASK"], typing.Any
+]
diff --git a/common/generated/rest/types/detect_entity_entity_type.py b/common/generated/rest/types/detect_entity_entity_type.py
new file mode 100644
index 00000000..dd61606a
--- /dev/null
+++ b/common/generated/rest/types/detect_entity_entity_type.py
@@ -0,0 +1,80 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+DetectEntityEntityType = typing.Union[
+ typing.Literal[
+ "NONE",
+ "BANK_ACCOUNT",
+ "CREDIT_CARD",
+ "CREDIT_CARD_EXPIRATION",
+ "CVV",
+ "DATE",
+ "DATE_INTERVAL",
+ "DOB",
+ "DRIVER_LICENSE",
+ "EMAIL_ADDRESS",
+ "HEALTHCARE_NUMBER",
+ "IP_ADDRESS",
+ "LOCATION",
+ "NAME",
+ "NUMERICAL_PII",
+ "PHONE_NUMBER",
+ "SSN",
+ "URL",
+ "VEHICLE_ID",
+ "MEDICAL_CODE",
+ "NAME_FAMILY",
+ "NAME_GIVEN",
+ "ACCOUNT_NUMBER",
+ "EVENT",
+ "FILENAME",
+ "GENDER",
+ "LANGUAGE",
+ "LOCATION_ADDRESS",
+ "LOCATION_CITY",
+ "LOCATION_COORDINATE",
+ "LOCATION_COUNTRY",
+ "LOCATION_STATE",
+ "LOCATION_ZIP",
+ "MARITAL_STATUS",
+ "MONEY",
+ "NAME_MEDICAL_PROFESSIONAL",
+ "OCCUPATION",
+ "ORGANIZATION",
+ "ORGANIZATION_MEDICAL_FACILITY",
+ "ORIGIN",
+ "PASSPORT_NUMBER",
+ "PASSWORD",
+ "PHYSICAL_ATTRIBUTE",
+ "POLITICAL_AFFILIATION",
+ "RELIGION",
+ "TIME",
+ "USERNAME",
+ "ZODIAC_SIGN",
+ "BLOOD_TYPE",
+ "CONDITION",
+ "DOSE",
+ "DRUG",
+ "INJURY",
+ "MEDICAL_PROCESS",
+ "STATISTICS",
+ "ROUTING_NUMBER",
+ "CORPORATE_ACTION",
+ "FINANCIAL_METRIC",
+ "PRODUCT",
+ "TREND",
+ "DURATION",
+ "LOCATION_ADDRESS_STREET",
+ "AGE",
+ "SEXUALITY",
+ "EFFECT",
+ "PROJECT",
+ "ORGANIZATION_ID",
+ "DAY",
+ "MONTH",
+ "YEAR",
+ "ALL",
+ ],
+ typing.Any,
+]
diff --git a/common/generated/rest/types/detect_entity_include_prefix.py b/common/generated/rest/types/detect_entity_include_prefix.py
new file mode 100644
index 00000000..daa163a5
--- /dev/null
+++ b/common/generated/rest/types/detect_entity_include_prefix.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+DetectEntityIncludePrefix = typing.Union[typing.Literal["YES", "NO"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/types/detect_guardrails_response.py b/common/generated/rest/types/detect_guardrails_response_v2.py
similarity index 57%
rename from skyvault/skyflow/generated/rest/types/detect_guardrails_response.py
rename to common/generated/rest/types/detect_guardrails_response_v2.py
index 2290ac52..d502fedc 100644
--- a/skyvault/skyflow/generated/rest/types/detect_guardrails_response.py
+++ b/common/generated/rest/types/detect_guardrails_response_v2.py
@@ -3,11 +3,17 @@
import typing
import pydantic
+import typing_extensions
from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from .detect_guardrails_response_validation import DetectGuardrailsResponseValidation
+from ..core.serialization import FieldMetadata
+from .detect_guardrails_response_v2validation import DetectGuardrailsResponseV2Validation
-class DetectGuardrailsResponse(UniversalBaseModel):
+class DetectGuardrailsResponseV2(UniversalBaseModel):
+ """
+ Response object for detect guardrails
+ """
+
text: str = pydantic.Field()
"""
Text that was checked against guardrails.
@@ -18,12 +24,16 @@ class DetectGuardrailsResponse(UniversalBaseModel):
Whether the text is toxic.
"""
- denied_topic: typing.Optional[bool] = pydantic.Field(default=None)
+ denied_topic: typing_extensions.Annotated[
+ typing.Optional[bool],
+ FieldMetadata(alias="deniedTopic"),
+ pydantic.Field(alias="deniedTopic", description="Whether the text included a denied topic."),
+ ] = None
"""
Whether the text included a denied topic.
"""
- validation: DetectGuardrailsResponseValidation = pydantic.Field()
+ validation: DetectGuardrailsResponseV2Validation = pydantic.Field()
"""
Whether the text passed validation.
"""
diff --git a/common/generated/rest/types/detect_guardrails_response_v2validation.py b/common/generated/rest/types/detect_guardrails_response_v2validation.py
new file mode 100644
index 00000000..5e9cdcc2
--- /dev/null
+++ b/common/generated/rest/types/detect_guardrails_response_v2validation.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+DetectGuardrailsResponseV2Validation = typing.Union[typing.Literal["FAILED", "PASSED"], typing.Any]
diff --git a/common/generated/rest/types/detect_object_entity.py b/common/generated/rest/types/detect_object_entity.py
new file mode 100644
index 00000000..8630f51e
--- /dev/null
+++ b/common/generated/rest/types/detect_object_entity.py
@@ -0,0 +1,43 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+import typing_extensions
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from ..core.serialization import FieldMetadata
+from .detect_object_entity_deidentification_type import DetectObjectEntityDeidentificationType
+from .detect_object_entity_entity_type import DetectObjectEntityEntityType
+
+
+class DetectObjectEntity(UniversalBaseModel):
+ """
+ Object entity detection and deidentification configuration (e.g. faces, license plates).
+ """
+
+ entity_type: typing_extensions.Annotated[
+ typing.Optional[DetectObjectEntityEntityType],
+ FieldMetadata(alias="entityType"),
+ pydantic.Field(alias="entityType", description="Type of entity to detect."),
+ ] = None
+ """
+ Type of entity to detect.
+ """
+
+ deidentification_type: typing_extensions.Annotated[
+ typing.Optional[DetectObjectEntityDeidentificationType],
+ FieldMetadata(alias="deidentificationType"),
+ pydantic.Field(alias="deidentificationType", description="Type of deidentification to apply."),
+ ] = None
+ """
+ Type of deidentification to apply.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/common/generated/rest/types/detect_object_entity_deidentification_type.py b/common/generated/rest/types/detect_object_entity_deidentification_type.py
new file mode 100644
index 00000000..918b5cef
--- /dev/null
+++ b/common/generated/rest/types/detect_object_entity_deidentification_type.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+DetectObjectEntityDeidentificationType = typing.Union[typing.Literal["UNKNOWN", "REDACT", "UNREDACT"], typing.Any]
diff --git a/common/generated/rest/types/detect_object_entity_entity_type.py b/common/generated/rest/types/detect_object_entity_entity_type.py
new file mode 100644
index 00000000..abefdfd6
--- /dev/null
+++ b/common/generated/rest/types/detect_object_entity_entity_type.py
@@ -0,0 +1,7 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+DetectObjectEntityEntityType = typing.Union[
+ typing.Literal["NONE", "FACE", "LICENSE_PLATE", "LOGO", "SIGNATURE", "ALL"], typing.Any
+]
diff --git a/common/generated/rest/types/detect_return_entities.py b/common/generated/rest/types/detect_return_entities.py
new file mode 100644
index 00000000..85c24c05
--- /dev/null
+++ b/common/generated/rest/types/detect_return_entities.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+DetectReturnEntities = typing.Union[typing.Literal["EXCLUDE_SENSITIVE_DATA", "ALL", "NONE"], typing.Any]
diff --git a/common/generated/rest/types/detect_runs_response_v2.py b/common/generated/rest/types/detect_runs_response_v2.py
new file mode 100644
index 00000000..562796cc
--- /dev/null
+++ b/common/generated/rest/types/detect_runs_response_v2.py
@@ -0,0 +1,56 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+import typing_extensions
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from ..core.serialization import FieldMetadata
+from .detect_runs_response_v2output_type import DetectRunsResponseV2OutputType
+from .detect_runs_response_v2status import DetectRunsResponseV2Status
+from .file_output import FileOutput
+from .metrics import Metrics
+
+
+class DetectRunsResponseV2(UniversalBaseModel):
+ """
+ Response containing the status and output of a v2 detect run.
+ """
+
+ status: typing.Optional[DetectRunsResponseV2Status] = pydantic.Field(default=None)
+ """
+ Status of the detect run.
+ """
+
+ output_type: typing_extensions.Annotated[
+ typing.Optional[DetectRunsResponseV2OutputType],
+ FieldMetadata(alias="outputType"),
+ pydantic.Field(
+ alias="outputType",
+ description="Data source of the output file. `BASE64`: Base64-encoded file string. `SKYFLOW_ID`: Reference file by vault ID. `PRESIGNED_URL`: S3 presigned URL of input file.",
+ ),
+ ] = None
+ """
+ Data source of the output file. `BASE64`: Base64-encoded file string. `SKYFLOW_ID`: Reference file by vault ID. `PRESIGNED_URL`: S3 presigned URL of input file.
+ """
+
+ output: typing.Optional[typing.List[FileOutput]] = pydantic.Field(default=None)
+ """
+ Details of output files.
+ """
+
+ message: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Status details about the Detect run.
+ """
+
+ metrics: typing.Optional[Metrics] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/common/generated/rest/types/detect_runs_response_v2output_type.py b/common/generated/rest/types/detect_runs_response_v2output_type.py
new file mode 100644
index 00000000..c1406fc0
--- /dev/null
+++ b/common/generated/rest/types/detect_runs_response_v2output_type.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+DetectRunsResponseV2OutputType = typing.Union[typing.Literal["BASE64", "SKYFLOW_ID", "PRESIGNED_URL"], typing.Any]
diff --git a/common/generated/rest/types/detect_runs_response_v2status.py b/common/generated/rest/types/detect_runs_response_v2status.py
new file mode 100644
index 00000000..ca65c94c
--- /dev/null
+++ b/common/generated/rest/types/detect_runs_response_v2status.py
@@ -0,0 +1,7 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+DetectRunsResponseV2Status = typing.Union[
+ typing.Literal["UNKNOWN", "FAILED", "SUCCESS", "IN_PROGRESS", "QUEUED"], typing.Any
+]
diff --git a/skyvault/skyflow/generated/rest/types/transformations.py b/common/generated/rest/types/document_v2.py
similarity index 72%
rename from skyvault/skyflow/generated/rest/types/transformations.py
rename to common/generated/rest/types/document_v2.py
index 9895e2f6..da657a30 100644
--- a/skyvault/skyflow/generated/rest/types/transformations.py
+++ b/common/generated/rest/types/document_v2.py
@@ -4,15 +4,15 @@
import pydantic
from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from .shift_dates import ShiftDates
+from .document_v2pdf import DocumentV2Pdf
-class Transformations(UniversalBaseModel):
+class DocumentV2(UniversalBaseModel):
"""
- Transformations to apply to detected entities.
+ Document detection and deidentification configuration.
"""
- shift_dates: typing.Optional[ShiftDates] = None
+ pdf: typing.Optional[DocumentV2Pdf] = None
if IS_PYDANTIC_V2:
model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
diff --git a/common/generated/rest/types/document_v2pdf.py b/common/generated/rest/types/document_v2pdf.py
new file mode 100644
index 00000000..b7641aa9
--- /dev/null
+++ b/common/generated/rest/types/document_v2pdf.py
@@ -0,0 +1,53 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+import typing_extensions
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from ..core.serialization import FieldMetadata
+from .document_v2pdf_processing_mode import DocumentV2PdfProcessingMode
+
+
+class DocumentV2Pdf(UniversalBaseModel):
+ """
+ Advanced options for processing PDF documents.
+ """
+
+ processing_mode: typing_extensions.Annotated[
+ typing.Optional[DocumentV2PdfProcessingMode],
+ FieldMetadata(alias="processingMode"),
+ pydantic.Field(
+ alias="processingMode",
+ description="Processing mode for the PDF file. `TEXT_LAYER`: processes the PDF's native text layer and replaces detected entities with entity tokens (for example, `[NAME_1]`). Fast and accurate for PDFs with selectable text. `OCR`: processes the PDF as an image using optical character recognition and covers detected content with a gray box. Use for scanned or image-based PDFs. Because `OCR` rasterizes each page, the output PDF file size can be significantly larger than the input.",
+ ),
+ ] = None
+ """
+ Processing mode for the PDF file. `TEXT_LAYER`: processes the PDF's native text layer and replaces detected entities with entity tokens (for example, `[NAME_1]`). Fast and accurate for PDFs with selectable text. `OCR`: processes the PDF as an image using optical character recognition and covers detected content with a gray box. Use for scanned or image-based PDFs. Because `OCR` rasterizes each page, the output PDF file size can be significantly larger than the input.
+ """
+
+ density: typing.Optional[int] = pydantic.Field(default=None)
+ """
+ Pixel density at which to process the PDF file. Applies only when `processingMode` is `OCR`.
+ """
+
+ max_resolution: typing_extensions.Annotated[
+ typing.Optional[int],
+ FieldMetadata(alias="maxResolution"),
+ pydantic.Field(
+ alias="maxResolution",
+ description="Max resolution at which to process the PDF file. Applies only when `processingMode` is `OCR`.",
+ ),
+ ] = None
+ """
+ Max resolution at which to process the PDF file. Applies only when `processingMode` is `OCR`.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/common/generated/rest/types/document_v2pdf_processing_mode.py b/common/generated/rest/types/document_v2pdf_processing_mode.py
new file mode 100644
index 00000000..4d953764
--- /dev/null
+++ b/common/generated/rest/types/document_v2pdf_processing_mode.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+DocumentV2PdfProcessingMode = typing.Union[typing.Literal["NONE", "OCR", "TEXT_LAYER"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/types/audit_event_http_info.py b/common/generated/rest/types/entity_transformation.py
similarity index 60%
rename from skyvault/skyflow/generated/rest/types/audit_event_http_info.py
rename to common/generated/rest/types/entity_transformation.py
index 093119e3..ea73e218 100644
--- a/skyvault/skyflow/generated/rest/types/audit_event_http_info.py
+++ b/common/generated/rest/types/entity_transformation.py
@@ -6,18 +6,17 @@
import typing_extensions
from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
from ..core.serialization import FieldMetadata
+from .transformation_shift_dates import TransformationShiftDates
-class AuditEventHttpInfo(UniversalBaseModel):
- uri: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="URI")] = pydantic.Field(default=None)
+class EntityTransformation(UniversalBaseModel):
"""
- The http URI that is used.
+ Optional transformations to apply to detected entity values.
"""
- method: typing.Optional[str] = pydantic.Field(default=None)
- """
- http method used.
- """
+ shift_dates: typing_extensions.Annotated[
+ typing.Optional[TransformationShiftDates], FieldMetadata(alias="shiftDates"), pydantic.Field(alias="shiftDates")
+ ] = None
if IS_PYDANTIC_V2:
model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
diff --git a/skyvault/skyflow/generated/rest/types/identify_response.py b/common/generated/rest/types/error_response.py
similarity index 73%
rename from skyvault/skyflow/generated/rest/types/identify_response.py
rename to common/generated/rest/types/error_response.py
index 67786621..7c0491bb 100644
--- a/skyvault/skyflow/generated/rest/types/identify_response.py
+++ b/common/generated/rest/types/error_response.py
@@ -4,17 +4,11 @@
import pydantic
from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from .error_response_error import ErrorResponseError
-class IdentifyResponse(UniversalBaseModel):
- """
- Response after identifying text.
- """
-
- text: str = pydantic.Field()
- """
- Re-identified text.
- """
+class ErrorResponse(UniversalBaseModel):
+ error: ErrorResponseError
if IS_PYDANTIC_V2:
model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
diff --git a/skyvault/skyflow/generated/rest/types/audit_event_data.py b/common/generated/rest/types/error_response_error.py
similarity index 59%
rename from skyvault/skyflow/generated/rest/types/audit_event_data.py
rename to common/generated/rest/types/error_response_error.py
index 9449de24..13d9fc11 100644
--- a/skyvault/skyflow/generated/rest/types/audit_event_data.py
+++ b/common/generated/rest/types/error_response_error.py
@@ -4,17 +4,19 @@
import pydantic
from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from .http_code import HttpCode
-class AuditEventData(UniversalBaseModel):
+class ErrorResponseError(UniversalBaseModel):
+ grpc_code: int = pydantic.Field()
"""
- Any Sensitive data that needs to be wrapped.
+ gRPC status codes. See https://grpc.io/docs/guides/status-codes.
"""
- content: typing.Optional[str] = pydantic.Field(default=None)
- """
- The entire body of the data requested or the query fired.
- """
+ http_code: HttpCode
+ http_status: str
+ message: str
+ details: typing.Optional[typing.List[typing.Dict[str, typing.Any]]] = None
if IS_PYDANTIC_V2:
model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
diff --git a/common/generated/rest/types/file_mapping.py b/common/generated/rest/types/file_mapping.py
new file mode 100644
index 00000000..8cc92ba8
--- /dev/null
+++ b/common/generated/rest/types/file_mapping.py
@@ -0,0 +1,69 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+import typing_extensions
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from ..core.serialization import FieldMetadata
+
+
+class FileMapping(UniversalBaseModel):
+ """
+ Source and destination file paths for a deidentification job.
+ """
+
+ source: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Location of the source file.
+ """
+
+ destination: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Location of the target file.
+ """
+
+ output_file_name_suffix: typing_extensions.Annotated[
+ typing.Optional[str],
+ FieldMetadata(alias="outputFileNameSuffix"),
+ pydantic.Field(
+ alias="outputFileNameSuffix",
+ description='Suffix of the output file. For example, with outputFileNameSuffix = "_deidentified", "invoice.pdf" becomes "invoice_deidentified.pdf".',
+ ),
+ ] = None
+ """
+ Suffix of the output file. For example, with outputFileNameSuffix = "_deidentified", "invoice.pdf" becomes "invoice_deidentified.pdf".
+ """
+
+ entities_destination: typing_extensions.Annotated[
+ typing.Optional[str],
+ FieldMetadata(alias="entitiesDestination"),
+ pydantic.Field(
+ alias="entitiesDestination",
+ description='Location of the entities output, as "table.column". For example, "documents.entities_json". Must be in the same table as source. If unset, the entities output is not stored in the vault.',
+ ),
+ ] = None
+ """
+ Location of the entities output, as "table.column". For example, "documents.entities_json". Must be in the same table as source. If unset, the entities output is not stored in the vault.
+ """
+
+ object_entities_destination: typing_extensions.Annotated[
+ typing.Optional[str],
+ FieldMetadata(alias="objectEntitiesDestination"),
+ pydantic.Field(
+ alias="objectEntitiesDestination",
+ description='Location of the object entities output, as "table.column". For example, "documents.object_entities_json". Must be in the same table as source. If unset, the object entities output is not stored in the vault.',
+ ),
+ ] = None
+ """
+ Location of the object entities output, as "table.column". For example, "documents.object_entities_json". Must be in the same table as source. If unset, the object entities output is not stored in the vault.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/common/generated/rest/types/file_output.py b/common/generated/rest/types/file_output.py
new file mode 100644
index 00000000..dbfdb32d
--- /dev/null
+++ b/common/generated/rest/types/file_output.py
@@ -0,0 +1,52 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+import typing_extensions
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from ..core.serialization import FieldMetadata
+from .file_output_processed_file_extension import FileOutputProcessedFileExtension
+from .file_output_processed_file_type import FileOutputProcessedFileType
+
+
+class FileOutput(UniversalBaseModel):
+ """
+ Represents a single processed output file along with its type and format.
+ """
+
+ processed_file: typing_extensions.Annotated[
+ typing.Optional[str],
+ FieldMetadata(alias="processedFile"),
+ pydantic.Field(alias="processedFile", description="Value of the processed file."),
+ ] = None
+ """
+ Value of the processed file.
+ """
+
+ processed_file_type: typing_extensions.Annotated[
+ typing.Optional[FileOutputProcessedFileType],
+ FieldMetadata(alias="processedFileType"),
+ pydantic.Field(alias="processedFileType", description="Type of the processed file."),
+ ] = None
+ """
+ Type of the processed file.
+ """
+
+ processed_file_extension: typing_extensions.Annotated[
+ typing.Optional[FileOutputProcessedFileExtension],
+ FieldMetadata(alias="processedFileExtension"),
+ pydantic.Field(alias="processedFileExtension", description="Processed file extension."),
+ ] = None
+ """
+ Processed file extension.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/file_data_data_format.py b/common/generated/rest/types/file_output_processed_file_extension.py
similarity index 85%
rename from skyvault/skyflow/generated/rest/types/file_data_data_format.py
rename to common/generated/rest/types/file_output_processed_file_extension.py
index 48205005..a2609851 100644
--- a/skyvault/skyflow/generated/rest/types/file_data_data_format.py
+++ b/common/generated/rest/types/file_output_processed_file_extension.py
@@ -2,7 +2,7 @@
import typing
-FileDataDataFormat = typing.Union[
+FileOutputProcessedFileExtension = typing.Union[
typing.Literal[
"mp3",
"wav",
@@ -25,6 +25,8 @@
"xml",
"dcm",
"jsonl",
+ "zip",
+ "gif",
],
typing.Any,
]
diff --git a/common/generated/rest/types/file_output_processed_file_type.py b/common/generated/rest/types/file_output_processed_file_type.py
new file mode 100644
index 00000000..efd4e81e
--- /dev/null
+++ b/common/generated/rest/types/file_output_processed_file_type.py
@@ -0,0 +1,17 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+FileOutputProcessedFileType = typing.Union[
+ typing.Literal[
+ "NONE",
+ "REDACTED_FILE",
+ "REDACTED_TEXT",
+ "ENTITIES",
+ "REIDENTIFIED_FILE",
+ "REDACTED_TRANSCRIPTION",
+ "REDACTED_DEEPGRAM_TRANSCRIPTION_DIARIZE_JSON",
+ "OBJECT_ENTITIES",
+ ],
+ typing.Any,
+]
diff --git a/skyvault/skyflow/generated/rest/types/v_1_get_auth_token_response.py b/common/generated/rest/types/get_auth_token_response.py
similarity index 56%
rename from skyvault/skyflow/generated/rest/types/v_1_get_auth_token_response.py
rename to common/generated/rest/types/get_auth_token_response.py
index c4db65a0..59d63e68 100644
--- a/skyvault/skyflow/generated/rest/types/v_1_get_auth_token_response.py
+++ b/common/generated/rest/types/get_auth_token_response.py
@@ -8,17 +8,21 @@
from ..core.serialization import FieldMetadata
-class V1GetAuthTokenResponse(UniversalBaseModel):
- access_token: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="accessToken")] = (
- pydantic.Field(default=None)
- )
+class GetAuthTokenResponse(UniversalBaseModel):
+ access_token: typing_extensions.Annotated[
+ typing.Optional[str],
+ FieldMetadata(alias="accessToken"),
+ pydantic.Field(alias="accessToken", description="AccessToken."),
+ ] = None
"""
AccessToken.
"""
- token_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="tokenType")] = pydantic.Field(
- default=None
- )
+ token_type: typing_extensions.Annotated[
+ typing.Optional[str],
+ FieldMetadata(alias="tokenType"),
+ pydantic.Field(alias="tokenType", description="TokenType : Bearer."),
+ ] = None
"""
TokenType : Bearer.
"""
diff --git a/common/generated/rest/types/get_sts_token_response.py b/common/generated/rest/types/get_sts_token_response.py
new file mode 100644
index 00000000..3cf2e3c0
--- /dev/null
+++ b/common/generated/rest/types/get_sts_token_response.py
@@ -0,0 +1,46 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+import typing_extensions
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from ..core.serialization import FieldMetadata
+
+
+class GetStsTokenResponse(UniversalBaseModel):
+ access_token: typing_extensions.Annotated[
+ typing.Optional[str],
+ FieldMetadata(alias="accessToken"),
+ pydantic.Field(alias="accessToken", description="AccessToken."),
+ ] = None
+ """
+ AccessToken.
+ """
+
+ issued_token_type: typing_extensions.Annotated[
+ typing.Optional[str],
+ FieldMetadata(alias="issuedTokenType"),
+ pydantic.Field(alias="issuedTokenType", description="IssuedTokenType : urn:ietf:params:oauth:token-type:jwt."),
+ ] = None
+ """
+ IssuedTokenType : urn:ietf:params:oauth:token-type:jwt.
+ """
+
+ token_type: typing_extensions.Annotated[
+ typing.Optional[str],
+ FieldMetadata(alias="tokenType"),
+ pydantic.Field(alias="tokenType", description="TokenType : Bearer."),
+ ] = None
+ """
+ TokenType : Bearer.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/common/generated/rest/types/googlerpc_status.py b/common/generated/rest/types/googlerpc_status.py
deleted file mode 100644
index f0a885b4..00000000
--- a/common/generated/rest/types/googlerpc_status.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from .protobuf_any import ProtobufAny
-
-
-class GooglerpcStatus(UniversalBaseModel):
- code: typing.Optional[int] = None
- message: typing.Optional[str] = None
- details: typing.Optional[typing.List[ProtobufAny]] = None
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/common/generated/rest/types/http_code.py b/common/generated/rest/types/http_code.py
new file mode 100644
index 00000000..a40fefff
--- /dev/null
+++ b/common/generated/rest/types/http_code.py
@@ -0,0 +1,6 @@
+# This file was auto-generated by Fern from our API Definition.
+
+HttpCode = int
+"""
+HTTP status codes. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Status.
+"""
diff --git a/common/generated/rest/types/image_v2.py b/common/generated/rest/types/image_v2.py
new file mode 100644
index 00000000..a5ce9816
--- /dev/null
+++ b/common/generated/rest/types/image_v2.py
@@ -0,0 +1,54 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+import typing_extensions
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from ..core.serialization import FieldMetadata
+from .image_v2masking_method import ImageV2MaskingMethod
+
+
+class ImageV2(UniversalBaseModel):
+ """
+ Image detection and deidentification configuration.
+ """
+
+ output_processed_image: typing_extensions.Annotated[
+ typing.Optional[bool],
+ FieldMetadata(alias="outputProcessedImage"),
+ pydantic.Field(alias="outputProcessedImage", description="If `true`, includes processed image in the output."),
+ ] = None
+ """
+ If `true`, includes processed image in the output.
+ """
+
+ output_ocr_text: typing_extensions.Annotated[
+ typing.Optional[bool],
+ FieldMetadata(alias="outputOcrText"),
+ pydantic.Field(alias="outputOcrText", description="If `true`, includes text detected by OCR in the response."),
+ ] = None
+ """
+ If `true`, includes text detected by OCR in the response.
+ """
+
+ masking_method: typing_extensions.Annotated[
+ typing.Optional[ImageV2MaskingMethod],
+ FieldMetadata(alias="maskingMethod"),
+ pydantic.Field(
+ alias="maskingMethod",
+ description="Method used to mask detected entities in the image. `BLUR`: blurs each detected entity so the sensitive content is unreadable while the rest of the image is preserved. `BLACKBOX`: covers each detected entity with a solid black box.",
+ ),
+ ] = None
+ """
+ Method used to mask detected entities in the image. `BLUR`: blurs each detected entity so the sensitive content is unreadable while the rest of the image is preserved. `BLACKBOX`: covers each detected entity with a solid black box.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/common/generated/rest/types/image_v2masking_method.py b/common/generated/rest/types/image_v2masking_method.py
new file mode 100644
index 00000000..b870c654
--- /dev/null
+++ b/common/generated/rest/types/image_v2masking_method.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+ImageV2MaskingMethod = typing.Union[typing.Literal["NONE", "BLUR", "BLACKBOX"], typing.Any]
diff --git a/common/generated/rest/types/media.py b/common/generated/rest/types/media.py
new file mode 100644
index 00000000..78153b9e
--- /dev/null
+++ b/common/generated/rest/types/media.py
@@ -0,0 +1,28 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from .audio_v2 import AudioV2
+from .document_v2 import DocumentV2
+from .image_v2 import ImageV2
+
+
+class Media(UniversalBaseModel):
+ """
+ Media-specific detection and deidentification configuration.
+ """
+
+ audio: typing.Optional[AudioV2] = None
+ document: typing.Optional[DocumentV2] = None
+ image: typing.Optional[ImageV2] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/common/generated/rest/types/metrics.py b/common/generated/rest/types/metrics.py
new file mode 100644
index 00000000..efa274ad
--- /dev/null
+++ b/common/generated/rest/types/metrics.py
@@ -0,0 +1,61 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+import typing_extensions
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from ..core.serialization import FieldMetadata
+
+
+class Metrics(UniversalBaseModel):
+ """
+ Performance metrics for the detection and deidentification operation.
+ """
+
+ size: typing.Optional[float] = pydantic.Field(default=None)
+ """
+ Size of the input text(KB).
+ """
+
+ word_count: typing_extensions.Annotated[
+ typing.Optional[int],
+ FieldMetadata(alias="wordCount"),
+ pydantic.Field(alias="wordCount", description="Total number of words processed."),
+ ] = None
+ """
+ Total number of words processed.
+ """
+
+ character_count: typing_extensions.Annotated[
+ typing.Optional[int],
+ FieldMetadata(alias="characterCount"),
+ pydantic.Field(alias="characterCount", description="Total number of characters processed."),
+ ] = None
+ """
+ Total number of characters processed.
+ """
+
+ slides: typing.Optional[int] = pydantic.Field(default=None)
+ """
+ Total number of slides processed.
+ """
+
+ pages: typing.Optional[int] = pydantic.Field(default=None)
+ """
+ Total number of pages processed.
+ """
+
+ duration: typing.Optional[float] = pydantic.Field(default=None)
+ """
+ Total duration processed(seconds).
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/common/generated/rest/types/protobuf_any.py b/common/generated/rest/types/protobuf_any.py
deleted file mode 100644
index 9062870c..00000000
--- a/common/generated/rest/types/protobuf_any.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-import typing_extensions
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from ..core.serialization import FieldMetadata
-
-
-class ProtobufAny(UniversalBaseModel):
- type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="@type")] = None
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/common/generated/rest/types/redaction_level.py b/common/generated/rest/types/redaction_level.py
new file mode 100644
index 00000000..c0de7cd2
--- /dev/null
+++ b/common/generated/rest/types/redaction_level.py
@@ -0,0 +1,73 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+import typing_extensions
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from ..core.serialization import FieldMetadata
+from .redaction_level_entity_name import RedactionLevelEntityName
+from .redaction_level_redaction_type import RedactionLevelRedactionType
+
+
+class RedactionLevel(UniversalBaseModel):
+ """
+ Specifies a replacement pattern/type and the token group or entity type it applies to during re-identification.
+ """
+
+ token_group_name: typing_extensions.Annotated[
+ typing.Optional[str],
+ FieldMetadata(alias="tokenGroupName"),
+ pydantic.Field(
+ alias="tokenGroupName",
+ description="Name of the token group whose detokenized values should be masked (e.g., a token in `personTokenGroup` that detokenizes to `John Doe` is masked as `JoXXXe`). Use this for FlowVault.",
+ ),
+ ] = None
+ """
+ Name of the token group whose detokenized values should be masked (e.g., a token in `personTokenGroup` that detokenizes to `John Doe` is masked as `JoXXXe`). Use this for FlowVault.
+ """
+
+ entity_name: typing_extensions.Annotated[
+ typing.Optional[RedactionLevelEntityName],
+ FieldMetadata(alias="entityName"),
+ pydantic.Field(
+ alias="entityName",
+ description="Entity type whose detokenized values should be shown in plain text, redacted, or masked based on `redactionType` (e.g., a `NAME` entity that detokenizes to `John Doe` is masked as `JoXXXe`). Use this for SkyVault.",
+ ),
+ ] = None
+ """
+ Entity type whose detokenized values should be shown in plain text, redacted, or masked based on `redactionType` (e.g., a `NAME` entity that detokenizes to `John Doe` is masked as `JoXXXe`). Use this for SkyVault.
+ """
+
+ redaction_type: typing_extensions.Annotated[
+ typing.Optional[RedactionLevelRedactionType],
+ FieldMetadata(alias="redactionType"),
+ pydantic.Field(
+ alias="redactionType",
+ description="Redaction method to apply to the detokenized value (e.g., for the value `John Doe`, `MASKED` transforms it into `JoXXXe`, `REDACTED` transforms it into `*REDACTED*`, and `PLAIN_TEXT` keeps it as `John Doe`). Use this for SkyVault.",
+ ),
+ ] = None
+ """
+ Redaction method to apply to the detokenized value (e.g., for the value `John Doe`, `MASKED` transforms it into `JoXXXe`, `REDACTED` transforms it into `*REDACTED*`, and `PLAIN_TEXT` keeps it as `John Doe`). Use this for SkyVault.
+ """
+
+ redaction_pattern: typing_extensions.Annotated[
+ typing.Optional[str],
+ FieldMetadata(alias="redactionPattern"),
+ pydantic.Field(
+ alias="redactionPattern",
+ description="Redaction method to apply to the detokenized value. Use the name of a redaction pattern configured in the vault (e.g., `personMaskPattern` transforms `John Doe` into `JoXXXe`). Use this for FlowVault.",
+ ),
+ ] = None
+ """
+ Redaction method to apply to the detokenized value. Use the name of a redaction pattern configured in the vault (e.g., `personMaskPattern` transforms `John Doe` into `JoXXXe`). Use this for FlowVault.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/common/generated/rest/types/redaction_level_entity_name.py b/common/generated/rest/types/redaction_level_entity_name.py
new file mode 100644
index 00000000..4a1a6b02
--- /dev/null
+++ b/common/generated/rest/types/redaction_level_entity_name.py
@@ -0,0 +1,80 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+RedactionLevelEntityName = typing.Union[
+ typing.Literal[
+ "NONE",
+ "BANK_ACCOUNT",
+ "CREDIT_CARD",
+ "CREDIT_CARD_EXPIRATION",
+ "CVV",
+ "DATE",
+ "DATE_INTERVAL",
+ "DOB",
+ "DRIVER_LICENSE",
+ "EMAIL_ADDRESS",
+ "HEALTHCARE_NUMBER",
+ "IP_ADDRESS",
+ "LOCATION",
+ "NAME",
+ "NUMERICAL_PII",
+ "PHONE_NUMBER",
+ "SSN",
+ "URL",
+ "VEHICLE_ID",
+ "MEDICAL_CODE",
+ "NAME_FAMILY",
+ "NAME_GIVEN",
+ "ACCOUNT_NUMBER",
+ "EVENT",
+ "FILENAME",
+ "GENDER",
+ "LANGUAGE",
+ "LOCATION_ADDRESS",
+ "LOCATION_CITY",
+ "LOCATION_COORDINATE",
+ "LOCATION_COUNTRY",
+ "LOCATION_STATE",
+ "LOCATION_ZIP",
+ "MARITAL_STATUS",
+ "MONEY",
+ "NAME_MEDICAL_PROFESSIONAL",
+ "OCCUPATION",
+ "ORGANIZATION",
+ "ORGANIZATION_MEDICAL_FACILITY",
+ "ORIGIN",
+ "PASSPORT_NUMBER",
+ "PASSWORD",
+ "PHYSICAL_ATTRIBUTE",
+ "POLITICAL_AFFILIATION",
+ "RELIGION",
+ "TIME",
+ "USERNAME",
+ "ZODIAC_SIGN",
+ "BLOOD_TYPE",
+ "CONDITION",
+ "DOSE",
+ "DRUG",
+ "INJURY",
+ "MEDICAL_PROCESS",
+ "STATISTICS",
+ "ROUTING_NUMBER",
+ "CORPORATE_ACTION",
+ "FINANCIAL_METRIC",
+ "PRODUCT",
+ "TREND",
+ "DURATION",
+ "LOCATION_ADDRESS_STREET",
+ "AGE",
+ "SEXUALITY",
+ "EFFECT",
+ "PROJECT",
+ "ORGANIZATION_ID",
+ "DAY",
+ "MONTH",
+ "YEAR",
+ "ALL",
+ ],
+ typing.Any,
+]
diff --git a/common/generated/rest/types/redaction_level_redaction_type.py b/common/generated/rest/types/redaction_level_redaction_type.py
new file mode 100644
index 00000000..2c50a350
--- /dev/null
+++ b/common/generated/rest/types/redaction_level_redaction_type.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+RedactionLevelRedactionType = typing.Union[typing.Literal["DEFAULT", "REDACTED", "MASKED", "PLAIN_TEXT"], typing.Any]
diff --git a/common/generated/rest/types/reidentify_file_response_v2.py b/common/generated/rest/types/reidentify_file_response_v2.py
new file mode 100644
index 00000000..dc8801c3
--- /dev/null
+++ b/common/generated/rest/types/reidentify_file_response_v2.py
@@ -0,0 +1,51 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+import typing_extensions
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from ..core.serialization import FieldMetadata
+from .file_output import FileOutput
+from .metrics import Metrics
+from .reidentify_file_response_v2output_type import ReidentifyFileResponseV2OutputType
+from .reidentify_file_response_v2status import ReidentifyFileResponseV2Status
+
+
+class ReidentifyFileResponseV2(UniversalBaseModel):
+ """
+ Response containing the status and output of a file reidentification job.
+ """
+
+ status: typing.Optional[ReidentifyFileResponseV2Status] = pydantic.Field(default=None)
+ """
+ Status of the reidentification request.
+ """
+
+ output_type: typing_extensions.Annotated[
+ typing.Optional[ReidentifyFileResponseV2OutputType],
+ FieldMetadata(alias="outputType"),
+ pydantic.Field(
+ alias="outputType",
+ description="Data source of the output file. `BASE64`: Base64-encoded file string. `SKYFLOW_ID`: Reference file by vault ID. `PRESIGNED_URL`: S3 presigned URL of input file.",
+ ),
+ ] = None
+ """
+ Data source of the output file. `BASE64`: Base64-encoded file string. `SKYFLOW_ID`: Reference file by vault ID. `PRESIGNED_URL`: S3 presigned URL of input file.
+ """
+
+ output: typing.Optional[typing.List[FileOutput]] = pydantic.Field(default=None)
+ """
+ Details of output files
+ """
+
+ metrics: typing.Optional[Metrics] = None
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/common/generated/rest/types/reidentify_file_response_v2output_type.py b/common/generated/rest/types/reidentify_file_response_v2output_type.py
new file mode 100644
index 00000000..220cfc78
--- /dev/null
+++ b/common/generated/rest/types/reidentify_file_response_v2output_type.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+ReidentifyFileResponseV2OutputType = typing.Union[typing.Literal["BASE64", "SKYFLOW_ID", "PRESIGNED_URL"], typing.Any]
diff --git a/common/generated/rest/types/reidentify_file_response_v2status.py b/common/generated/rest/types/reidentify_file_response_v2status.py
new file mode 100644
index 00000000..fc1653e5
--- /dev/null
+++ b/common/generated/rest/types/reidentify_file_response_v2status.py
@@ -0,0 +1,7 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+ReidentifyFileResponseV2Status = typing.Union[
+ typing.Literal["UNKNOWN", "FAILED", "SUCCESS", "IN_PROGRESS", "QUEUED"], typing.Any
+]
diff --git a/skyvault/skyflow/generated/rest/types/upload_file_v_2_response.py b/common/generated/rest/types/reidentify_string_response_v2.py
similarity index 55%
rename from skyvault/skyflow/generated/rest/types/upload_file_v_2_response.py
rename to common/generated/rest/types/reidentify_string_response_v2.py
index f1bcc215..f1f56319 100644
--- a/skyvault/skyflow/generated/rest/types/upload_file_v_2_response.py
+++ b/common/generated/rest/types/reidentify_string_response_v2.py
@@ -6,23 +6,24 @@
import typing_extensions
from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
from ..core.serialization import FieldMetadata
+from .metrics import Metrics
-class UploadFileV2Response(UniversalBaseModel):
+class ReidentifyStringResponseV2(UniversalBaseModel):
"""
- Response schema for uploading a file, optionally creating a new record.
+ Response containing the reidentified string with tokens replaced by original values.
"""
- skyflow_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="skyflowID")] = pydantic.Field(
- default=None
- )
+ processed_text: typing_extensions.Annotated[
+ typing.Optional[str],
+ FieldMetadata(alias="processedText"),
+ pydantic.Field(alias="processedText", description="Reidentified text."),
+ ] = None
"""
- Skyflow ID of the record the file was uploaded to.
+ Reidentified text.
"""
- file_metadata: typing_extensions.Annotated[
- typing.Optional[typing.Optional[typing.Any]], FieldMetadata(alias="fileMetadata")
- ] = None
+ metrics: typing.Optional[Metrics] = None
if IS_PYDANTIC_V2:
model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
diff --git a/common/generated/rest/types/transformation_shift_dates.py b/common/generated/rest/types/transformation_shift_dates.py
new file mode 100644
index 00000000..6796ea4a
--- /dev/null
+++ b/common/generated/rest/types/transformation_shift_dates.py
@@ -0,0 +1,41 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+import typing_extensions
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from ..core.serialization import FieldMetadata
+
+
+class TransformationShiftDates(UniversalBaseModel):
+ """
+ Shifts detected date values by a random number of days within the given range. Negative values shift dates backward and positive values shift them forward.
+ """
+
+ min_days: typing_extensions.Annotated[
+ typing.Optional[int],
+ FieldMetadata(alias="minDays"),
+ pydantic.Field(alias="minDays", description="Minimum number of days to shift dates."),
+ ] = None
+ """
+ Minimum number of days to shift dates.
+ """
+
+ max_days: typing_extensions.Annotated[
+ typing.Optional[int],
+ FieldMetadata(alias="maxDays"),
+ pydantic.Field(alias="maxDays", description="Maximum number of days to shift dates."),
+ ] = None
+ """
+ Maximum number of days to shift dates.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/common/generated/rest/types/v_1_get_auth_token_response.py b/common/generated/rest/types/v_1_get_auth_token_response.py
deleted file mode 100644
index c4db65a0..00000000
--- a/common/generated/rest/types/v_1_get_auth_token_response.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-import typing_extensions
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from ..core.serialization import FieldMetadata
-
-
-class V1GetAuthTokenResponse(UniversalBaseModel):
- access_token: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="accessToken")] = (
- pydantic.Field(default=None)
- )
- """
- AccessToken.
- """
-
- token_type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="tokenType")] = pydantic.Field(
- default=None
- )
- """
- TokenType : Bearer.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/common/generated/rest/version.py b/common/generated/rest/version.py
index 4f3bb47a..52dce935 100644
--- a/common/generated/rest/version.py
+++ b/common/generated/rest/version.py
@@ -1,6 +1,6 @@
-# NOTE: hand-patched, not Fern-generated content. Fern originally emitted a runtime
-# metadata.version("skyflow.generated.rest") lookup here, but this code is bundled into the
-# skyflow (v2) and v3 wheels via a build_py hook rather than published under that distribution
-# name, so the lookup always raised PackageNotFoundError on import. Hardcoded until the Fern
-# generator config (skyflow-fern-config) is updated to stop emitting a runtime lookup here.
-__version__ = "0.0.9"
+from importlib import metadata
+
+try:
+ __version__ = metadata.version("skyflow-common")
+except metadata.PackageNotFoundError:
+ __version__ = "0.0.0"
diff --git a/common/service_account/_utils.py b/common/service_account/_utils.py
index 63f3ddfd..43f67f79 100644
--- a/common/service_account/_utils.py
+++ b/common/service_account/_utils.py
@@ -149,8 +149,8 @@ def get_service_account_token(credentials, options, logger):
formatted_scope = format_scope(options.get(OptionField.ROLE_IDS))
try:
- response = auth_api.authentication_service_get_auth_token(assertion = signed_token,
- grant_type=JWT.GRANT_TYPE_JWT_BEARER,
+ response = auth_api.get_bearer_token(grant_type=JWT.GRANT_TYPE_JWT_BEARER,
+ assertion=signed_token,
scope=formatted_scope)
log_info(SkyflowMessages.Info.GET_BEARER_TOKEN_SUCCESS.value, logger)
except UnauthorizedError:
diff --git a/common/tests/vault/detect/__init__.py b/common/tests/vault/detect/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/common/tests/vault/detect/test_detect.py b/common/tests/vault/detect/test_detect.py
new file mode 100644
index 00000000..219df8c3
--- /dev/null
+++ b/common/tests/vault/detect/test_detect.py
@@ -0,0 +1,345 @@
+import base64
+import os
+import shutil
+import tempfile
+import unittest
+from enum import Enum
+from types import SimpleNamespace
+
+from common.errors import SkyflowError
+from common.utils.enums.detect import (
+ DeidentificationType,
+ DetectRunStatus,
+ EntityType,
+ FileDataFormat,
+ GuardrailsValidation,
+)
+
+
+class DeidentifySourceType(Enum):
+ BASE64 = "BASE64"
+ SKYFLOW_ID = "SKYFLOW_ID"
+ PRESIGNED_URL = "PRESIGNED_URL"
+
+
+class ReidentifySourceType(Enum):
+ BASE64 = "BASE64"
+ PRESIGNED_URL = "PRESIGNED_URL"
+from common.utils.enums.redaction_type import RedactionType
+from common.vault.detect import (
+ CheckGuardrailsRequest,
+ DeidentifyFileRequest,
+ DeidentifyStringRequest,
+ DetectConfiguration,
+ Detect,
+ DetectController,
+ Entity,
+ GetRunRequest,
+ PollOptions,
+ RedactionRule,
+ ReidentifyFileRequest,
+ ReidentifyStringRequest,
+)
+from common.vault.detect import _file_output_writer as writer
+from common.vault.detect import _mappers as mappers
+from common.vault.detect import _polling as polling
+from common.vault.detect import _validations as validations
+
+VAULT_ID = "vault123"
+TOKEN = "bearer-token"
+
+
+class _EntityRedactionRule(RedactionRule):
+ def __init__(self, entity_name=None, redaction_type=None):
+ self.entity_name = entity_name
+ self.redaction_type = redaction_type
+
+ def _api_entity_name(self):
+ return self.entity_name
+
+ def _api_redaction_type(self):
+ return self.redaction_type
+
+
+class _Raw:
+ def __init__(self, data):
+ self._data = data
+ self.calls = []
+
+ def __getattr__(self, name):
+ if name.startswith("_"):
+ raise AttributeError(name)
+
+ def method(*args, **kwargs):
+ self.calls.append((name, args, kwargs))
+ return SimpleNamespace(data=self._data, headers={})
+
+ return method
+
+
+class _FilesRaw:
+ def __init__(self, run_id, run_data=None, reidentify_data=None):
+ self.run_id = run_id
+ self.run_data = list(run_data or [])
+ self.reidentify_data = reidentify_data
+ self.calls = []
+
+ def deidentify_file_v2(self, **kwargs):
+ self.calls.append(("deidentify_file_v2", (), kwargs))
+ return SimpleNamespace(data=SimpleNamespace(run_id=self.run_id), headers={})
+
+ def get_run_v2(self, run_id, **kwargs):
+ self.calls.append(("get_run_v2", (run_id,), kwargs))
+ return SimpleNamespace(data=self.run_data.pop(0), headers={})
+
+ def reidentify_file_v2(self, **kwargs):
+ self.calls.append(("reidentify_file_v2", (), kwargs))
+ return SimpleNamespace(data=self.reidentify_data, headers={})
+
+
+def _api(raw):
+ return SimpleNamespace(with_raw_response=raw)
+
+
+def _vault_client(strings=None, files=None, guardrails=None):
+ return SimpleNamespace(
+ get_logger=lambda: None,
+ get_vault_id=lambda: VAULT_ID,
+ get_current_bearer_token=lambda: TOKEN,
+ get_sdk_metrics=lambda: {},
+ initialize_client_configuration=lambda: None,
+ get_strings_v2_api=lambda: _api(strings),
+ get_files_v2_api=lambda: _api(files),
+ get_guardrails_v2_api=lambda: _api(guardrails),
+ get_deidentify_source_type=lambda: DeidentifySourceType,
+ get_reidentify_source_type=lambda: ReidentifySourceType,
+ )
+
+
+def _metrics():
+ return SimpleNamespace(size=1.5, word_count=10, character_count=53, slides=None, pages=2, duration=None)
+
+
+class TestDetectController(unittest.TestCase):
+ def test_deidentify_string_maps_request_and_response(self):
+ entity = SimpleNamespace(
+ token="NAME_1", value="", entity_type="NAME",
+ entity_scores={"NAME": 0.9152},
+ location=SimpleNamespace(start_index=11, end_index=19, start_index_processed=11, end_index_processed=19),
+ )
+ data = SimpleNamespace(processed_text="My name is [NAME_1]", entities=[entity], metrics=_metrics())
+ raw = _Raw(data)
+ controller = DetectController(_vault_client(strings=raw))
+
+ response = controller.deidentify_string(DeidentifyStringRequest(text="My name is John Doe", configuration_id="cfg"))
+
+ name, _args, kwargs = raw.calls[0]
+ self.assertEqual(name, "deidentify_string_v2")
+ self.assertEqual(kwargs["text"], "My name is John Doe")
+ self.assertEqual(kwargs["configuration_id"], "cfg")
+ self.assertNotIn("configuration", kwargs)
+ headers = kwargs["request_options"]["additional_headers"]
+ self.assertEqual(headers["Authorization"], "Bearer " + TOKEN)
+ self.assertIn("sky-metadata", headers)
+ self.assertEqual(response.processed_text, "My name is [NAME_1]")
+ self.assertEqual(response.entities[0].token, "NAME_1")
+ self.assertEqual(response.entities[0].entity_type, "NAME")
+ self.assertEqual(response.entities[0].location.start_index, 11)
+ self.assertEqual(response.metrics.character_count, 53)
+
+ def test_deidentify_string_inline_config_injects_vault_id(self):
+ raw = _Raw(SimpleNamespace(processed_text="x", entities=None, metrics=None))
+ controller = DetectController(_vault_client(strings=raw))
+ configuration = DetectConfiguration(detect=Detect(entities=[
+ Entity(entity_type=EntityType.NAME, deidentification_type=DeidentificationType.VAULT_TOKEN, destination="persons.name"),
+ ]))
+
+ controller.deidentify_string(DeidentifyStringRequest(text="hi", configuration=configuration))
+
+ _name, _args, kwargs = raw.calls[0]
+ self.assertNotIn("configuration_id", kwargs)
+ wire = kwargs["configuration"].dict(by_alias=True, exclude_none=True)
+ self.assertEqual(wire["vaultId"], VAULT_ID)
+ self.assertEqual(wire["detect"]["entities"][0]["entityType"], "NAME")
+ self.assertEqual(wire["detect"]["entities"][0]["deidentificationType"], "VAULT_TOKEN")
+
+ def test_reidentify_string_sends_vault_id(self):
+ raw = _Raw(SimpleNamespace(processed_text="My name is John Doe", metrics=None))
+ controller = DetectController(_vault_client(strings=raw))
+
+ controller.reidentify_string(ReidentifyStringRequest(
+ text="My name is [NAME_1]",
+ redaction_level=[_EntityRedactionRule(entity_name=EntityType.NAME, redaction_type=RedactionType.PLAIN_TEXT)],
+ ))
+
+ _name, _args, kwargs = raw.calls[0]
+ self.assertEqual(kwargs["vault_id"], VAULT_ID)
+ self.assertEqual(kwargs["text"], "My name is [NAME_1]")
+ wire = [level.dict(by_alias=True, exclude_none=True) for level in kwargs["redaction_level"]]
+ self.assertEqual(wire, [{"entityName": "NAME", "redactionType": "PLAIN_TEXT"}])
+
+ def test_deidentify_file_submit_only_status_none(self):
+ files = _FilesRaw(run_id="run-1")
+ controller = DetectController(_vault_client(files=files))
+
+ response = controller.deidentify_file(DeidentifyFileRequest(
+ data_source=DeidentifySourceType.SKYFLOW_ID, value="sid", configuration_id="cfg",
+ ))
+
+ self.assertEqual(response.run_id, "run-1")
+ self.assertIsNone(response.status)
+ self.assertEqual(response.output, [])
+ self.assertEqual([c[0] for c in files.calls], ["deidentify_file_v2"])
+ _name, _args, kwargs = files.calls[0]
+ self.assertEqual(kwargs["data_source"], "SKYFLOW_ID")
+ self.assertEqual(kwargs["value"], "sid")
+
+ def test_deidentify_file_polled_success_writes(self):
+ tmp = tempfile.mkdtemp()
+ self.addCleanup(shutil.rmtree, tmp, ignore_errors=True)
+ input_file = os.path.join(tmp, "notes.pdf")
+ with open(input_file, "wb") as handle:
+ handle.write(b"input-bytes")
+ out_dir = os.path.join(tmp, "out")
+ os.makedirs(out_dir)
+ run_data = [SimpleNamespace(
+ status="SUCCESS", output_type="BASE64",
+ output=[SimpleNamespace(
+ processed_file=base64.b64encode(b"redacted").decode(), processed_file_type="REDACTED_FILE",
+ processed_file_extension="pdf",
+ )],
+ metrics=_metrics(), message=None,
+ )]
+ files = _FilesRaw(run_id="run-2", run_data=run_data)
+ controller = DetectController(_vault_client(files=files))
+
+ response = controller.deidentify_file(DeidentifyFileRequest(
+ file_path=input_file, configuration_id="cfg",
+ poll_options=PollOptions(), output_directory=out_dir,
+ ))
+
+ submit = files.calls[0]
+ self.assertEqual(submit[0], "deidentify_file_v2")
+ self.assertEqual(submit[2]["data_source"], "BASE64")
+ self.assertEqual(submit[2]["value"], base64.b64encode(b"input-bytes").decode())
+ self.assertEqual(submit[2]["data_format"], "pdf")
+ self.assertEqual(response.status, DetectRunStatus.SUCCESS)
+ self.assertEqual(response.run_id, "run-2")
+ with open(os.path.join(out_dir, "processed-notes.pdf"), "rb") as handle:
+ self.assertEqual(handle.read(), b"redacted")
+
+ def test_get_run_trims_run_id_and_maps(self):
+ data = SimpleNamespace(status="IN_PROGRESS", output_type=None, output=None, metrics=None, message=None)
+ files = _FilesRaw(run_id="ignored", run_data=[data])
+ controller = DetectController(_vault_client(files=files))
+
+ response = controller.get_run(GetRunRequest(run_id=" run-9 "))
+
+ self.assertEqual(files.calls[0][1][0], "run-9")
+ self.assertEqual(response.run_id, "run-9")
+ self.assertEqual(response.status, DetectRunStatus.IN_PROGRESS)
+ self.assertEqual(response.output, [])
+
+ def test_check_guardrails_maps(self):
+ data = SimpleNamespace(text="prompt", validation="FAILED", toxic=True, denied_topic=False)
+ raw = _Raw(data)
+ controller = DetectController(_vault_client(guardrails=raw))
+
+ response = controller.check_guardrails(CheckGuardrailsRequest(text="prompt", check_toxicity=True, deny_topics=["politics"]))
+
+ _name, _args, kwargs = raw.calls[0]
+ self.assertEqual(kwargs["vault_id"], VAULT_ID)
+ self.assertIs(kwargs["check_toxicity"], True)
+ self.assertEqual(kwargs["deny_topics"], ["politics"])
+ self.assertEqual(response.validation, GuardrailsValidation.FAILED)
+ self.assertIs(response.toxic, True)
+
+ def test_reidentify_file_value_only(self):
+ data = SimpleNamespace(status="SUCCESS", output_type="BASE64", output=[], metrics=None)
+ files = _FilesRaw(run_id="n/a", reidentify_data=data)
+ controller = DetectController(_vault_client(files=files))
+
+ response = controller.reidentify_file(ReidentifyFileRequest(
+ data_source=ReidentifySourceType.BASE64, value="b64", data_format=FileDataFormat.TXT,
+ ))
+
+ _name, _args, kwargs = files.calls[0]
+ self.assertEqual(kwargs["data_source"], "BASE64")
+ self.assertEqual(kwargs["value"], "b64")
+ self.assertEqual(kwargs["vault_id"], VAULT_ID)
+ self.assertEqual(kwargs["data_format"], "txt")
+ self.assertEqual(response.status, DetectRunStatus.SUCCESS)
+
+ def test_poll_run_backoff_and_budget(self):
+ sleeps = []
+ responses = [mappers.to_get_run_response("r", SimpleNamespace(
+ status="QUEUED", output_type=None, output=None, metrics=None, message=None), DeidentifySourceType) for _ in range(20)]
+
+ def fetcher(_run_id):
+ return responses.pop(0)
+
+ run = polling.poll_run("r", PollOptions(), fetcher, sleeper=sleeps.append)
+
+ self.assertEqual(sleeps[:5], [1, 2, 4, 8, 16])
+ self.assertEqual(sum(sleeps), 60)
+ self.assertEqual(run.status, DetectRunStatus.QUEUED)
+
+ def test_poll_run_stops_on_terminal(self):
+ calls = {"n": 0}
+
+ def fetcher(_run_id):
+ calls["n"] += 1
+ status = "SUCCESS" if calls["n"] == 2 else "IN_PROGRESS"
+ return mappers.to_get_run_response("r", SimpleNamespace(
+ status=status, output_type=None, output=None, metrics=None, message=None), DeidentifySourceType)
+
+ sleeps = []
+ run = polling.poll_run("r", PollOptions(), fetcher, sleeper=sleeps.append)
+
+ self.assertEqual(calls["n"], 2)
+ self.assertEqual(sleeps, [1])
+ self.assertEqual(run.status, DetectRunStatus.SUCCESS)
+
+ def test_poll_run_null_status_is_terminal_unknown(self):
+ def fetcher(_run_id):
+ return None
+
+ sleeps = []
+ run = polling.poll_run("r", PollOptions(), fetcher, sleeper=sleeps.append)
+
+ self.assertEqual(sleeps, [])
+ self.assertEqual(run.status, DetectRunStatus.UNKNOWN)
+
+ def test_file_output_writer_names(self):
+ tmp = tempfile.mkdtemp()
+ self.addCleanup(shutil.rmtree, tmp, ignore_errors=True)
+ outputs = [
+ mappers.FileOutput(processed_file=base64.b64encode(b"a").decode(), processed_file_type="REDACTED_FILE", processed_file_extension=FileDataFormat.PDF),
+ mappers.FileOutput(processed_file=base64.b64encode(b"b").decode(), processed_file_type="ENTITIES", processed_file_extension=None),
+ ]
+ written = writer.write_outputs(outputs, DeidentifySourceType.BASE64, "invoice.pdf", tmp)
+ names = sorted(os.path.basename(path) for path in written)
+ self.assertEqual(names, ["processed-entities-invoice.json", "processed-invoice.pdf"])
+
+ def test_file_output_writer_skips_presigned(self):
+ outputs = [mappers.FileOutput(processed_file="http://x", processed_file_type="REDACTED_FILE", processed_file_extension=FileDataFormat.PDF)]
+ self.assertEqual(writer.write_outputs(outputs, DeidentifySourceType.PRESIGNED_URL, "a.pdf", None), [])
+
+ def test_validations(self):
+ with self.assertRaises(SkyflowError):
+ validations.validate_deidentify_string_request(DeidentifyStringRequest(text=" "))
+ with self.assertRaises(SkyflowError):
+ validations.validate_deidentify_file_request(DeidentifyFileRequest(data_source=DeidentifySourceType.BASE64, value="x", file_path="y"))
+ with self.assertRaises(SkyflowError):
+ validations.validate_deidentify_file_request(DeidentifyFileRequest(value="x", data_source=DeidentifySourceType.BASE64, poll_options=None, output_directory="d"))
+ with self.assertRaises(SkyflowError):
+ validations.validate_deidentify_file_request(DeidentifyFileRequest(value="x", data_source=DeidentifySourceType.BASE64, poll_options=PollOptions(wait_time=301)))
+ with self.assertRaises(SkyflowError):
+ validations.validate_reidentify_file_request(ReidentifyFileRequest(value="x"))
+ with self.assertRaises(SkyflowError):
+ validations.validate_get_run_request(GetRunRequest(run_id=" "))
+ validations.validate_deidentify_file_request(DeidentifyFileRequest(data_source=DeidentifySourceType.BASE64, value="x"))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/common/utils/_skyflow_messages.py b/common/utils/_skyflow_messages.py
index 16abacdc..73e2d585 100644
--- a/common/utils/_skyflow_messages.py
+++ b/common/utils/_skyflow_messages.py
@@ -1,11 +1,27 @@
import sys
from enum import Enum
-# `common` has no SDK_VERSION of its own -- picks up whichever variant is installed. Reads
-# sys.modules (never forces a fresh import) to avoid triggering a circular import back into
-# common.* mid-init.
-_version_module = sys.modules.get("skyflow.utils._version")
-SDK_VERSION = getattr(_version_module, "SDK_VERSION", "0.0.0")
+from importlib import metadata
+
+UNKNOWN_SDK_VERSION = "0.0.0"
+HOST_SDK_VERSION_MODULE = "skyflow.utils._version"
+HOST_SDK_DISTRIBUTIONS = ("skyflow", "skyflow-flowvault-python")
+
+
+def _resolve_sdk_version():
+ version_module = sys.modules.get(HOST_SDK_VERSION_MODULE)
+ version = getattr(version_module, "SDK_VERSION", None)
+ if version:
+ return version
+ for distribution in HOST_SDK_DISTRIBUTIONS:
+ try:
+ return metadata.version(distribution)
+ except metadata.PackageNotFoundError:
+ continue
+ return UNKNOWN_SDK_VERSION
+
+
+SDK_VERSION = _resolve_sdk_version()
error_prefix = f"Skyflow Python SDK {SDK_VERSION}"
INFO = "INFO"
@@ -234,6 +250,28 @@ class Error(Enum):
GET_DETECT_RUN_FAILED = f"{error_prefix} Get detect run operation failed."
BASE_SKYFLOW_INSTANTIATION_NOT_ALLOWED = f"{error_prefix} BaseSkyflow cannot be instantiated directly. Build a concrete Skyflow class via make_skyflow_class() instead."
+ DEIDENTIFY_STRING_REQUEST_NULL = f"{error_prefix} Validation error. DeidentifyString request cannot be null."
+ INVALID_TEXT_IN_DEIDENTIFY_STRING = f"{error_prefix} Validation error. Invalid text in deidentify string request. Specify a non-empty text."
+ DEIDENTIFY_FILE_REQUEST_NULL = f"{error_prefix} Validation error. DeidentifyFile request cannot be null."
+ MULTIPLE_FILE_SOURCES_IN_DEIDENTIFY_FILE = f"{error_prefix} Validation error. Specify either value or file in deidentify file request, not both."
+ FILE_NOT_FOUND_TO_DEIDENTIFY = f"{error_prefix} Validation error. The file to deidentify was not found at the specified path. Verify the file path and try again."
+ INVALID_DATA_SOURCE_IN_DEIDENTIFY_FILE = f"{error_prefix} Validation error. Invalid dataSource in deidentify file request. Specify BASE64, SKYFLOW_ID or PRESIGNED_URL, or supply a file."
+ INVALID_VALUE_IN_DEIDENTIFY_FILE = f"{error_prefix} Validation error. Invalid value in deidentify file request. Specify the non-empty base64 content, skyflow id or presigned URL of the file, or supply a file."
+ OUTPUT_DIRECTORY_WITHOUT_POLL_OPTIONS = f"{error_prefix} Validation error. output_directory in deidentify file request requires poll_options."
+ INVALID_WAIT_TIME_IN_POLL_OPTIONS = f"{error_prefix} Validation error. wait_time in poll_options must be between 1 and 300 seconds."
+ INVALID_MAX_ATTEMPTS_IN_POLL_OPTIONS = f"{error_prefix} Validation error. max_attempts in poll_options must be between 1 and 23."
+ REIDENTIFY_STRING_REQUEST_NULL = f"{error_prefix} Validation error. ReidentifyString request cannot be null."
+ INVALID_TEXT_IN_REIDENTIFY_STRING = f"{error_prefix} Validation error. Invalid text in reidentify string request. Specify a non-empty text."
+ GET_RUN_REQUEST_NULL = f"{error_prefix} Validation error. GetRun request cannot be null."
+ INVALID_RUN_ID_IN_GET_RUN = f"{error_prefix} Validation error. Invalid runId in get run request. Specify a non-empty run id."
+ CHECK_GUARDRAILS_REQUEST_NULL = f"{error_prefix} Validation error. CheckGuardrails request cannot be null."
+ INVALID_TEXT_IN_CHECK_GUARDRAILS = f"{error_prefix} Validation error. Invalid text in check guardrails request. Specify a non-empty text."
+ REIDENTIFY_FILE_REQUEST_NULL = f"{error_prefix} Validation error. ReidentifyFile request cannot be null."
+ INVALID_DATA_SOURCE_IN_REIDENTIFY_FILE = f"{error_prefix} Validation error. Invalid dataSource in reidentify file request. Specify BASE64, SKYFLOW_ID or PRESIGNED_URL."
+ INVALID_VALUE_IN_REIDENTIFY_FILE = f"{error_prefix} Validation error. Invalid value in reidentify file request. Specify the non-empty base64 content, skyflow id or presigned URL of the file."
+ FAILED_TO_ENCODE_FILE = f"{error_prefix} Validation error. Failed to encode the file. Ensure the file is in a supported format and try again."
+ FAILED_TO_WRITE_OUTPUT_FILE = f"{error_prefix} Failed to write the processed output to {{}}."
+
class Info(Enum):
CLIENT_INITIALIZED = f"{INFO}: [{error_prefix}] Initialized skyflow client."
VALIDATING_VAULT_CONFIG = f"{INFO}: [{error_prefix}] Validating vault config."
@@ -329,6 +367,33 @@ class Info(Enum):
DETECT_REQUEST_RESOLVED = f"{INFO}: [{error_prefix}] Detect request is resolved."
+ DEIDENTIFY_STRING_TRIGGERED = f"{INFO}: [{error_prefix}] Deidentify string method triggered."
+ VALIDATE_DEIDENTIFY_STRING_REQUEST = f"{INFO}: [{error_prefix}] Validating deidentify string request."
+ DEIDENTIFY_STRING_REQUEST_RESOLVED = f"{INFO}: [{error_prefix}] Deidentify string request resolved."
+ DEIDENTIFY_STRING_SUCCESS = f"{INFO}: [{error_prefix}] String deidentified."
+ REIDENTIFY_STRING_TRIGGERED = f"{INFO}: [{error_prefix}] Reidentify string method triggered."
+ VALIDATE_REIDENTIFY_STRING_REQUEST = f"{INFO}: [{error_prefix}] Validating reidentify string request."
+ REIDENTIFY_STRING_REQUEST_RESOLVED = f"{INFO}: [{error_prefix}] Reidentify string request resolved."
+ REIDENTIFY_STRING_SUCCESS = f"{INFO}: [{error_prefix}] String reidentified."
+ DEIDENTIFY_FILE_V2_TRIGGERED = f"{INFO}: [{error_prefix}] Deidentify file method triggered."
+ DEIDENTIFY_FILE_V2_REQUEST_RESOLVED = f"{INFO}: [{error_prefix}] Deidentify file request resolved."
+ DEIDENTIFY_FILE_V2_SUCCESS = f"{INFO}: [{error_prefix}] File deidentified."
+ REIDENTIFY_FILE_TRIGGERED = f"{INFO}: [{error_prefix}] Reidentify file method triggered."
+ VALIDATE_REIDENTIFY_FILE_REQUEST = f"{INFO}: [{error_prefix}] Validating reidentify file request."
+ REIDENTIFY_FILE_REQUEST_RESOLVED = f"{INFO}: [{error_prefix}] Reidentify file request resolved."
+ REIDENTIFY_FILE_SUCCESS = f"{INFO}: [{error_prefix}] File reidentified."
+ GET_RUN_TRIGGERED = f"{INFO}: [{error_prefix}] Get run method triggered."
+ VALIDATE_GET_RUN_REQUEST = f"{INFO}: [{error_prefix}] Validating get run request."
+ GET_RUN_REQUEST_RESOLVED = f"{INFO}: [{error_prefix}] Get run request resolved."
+ GET_RUN_SUCCESS = f"{INFO}: [{error_prefix}] Get run success."
+ CHECK_GUARDRAILS_TRIGGERED = f"{INFO}: [{error_prefix}] Check guardrails method triggered."
+ VALIDATE_CHECK_GUARDRAILS_REQUEST = f"{INFO}: [{error_prefix}] Validating check guardrails request."
+ CHECK_GUARDRAILS_REQUEST_RESOLVED = f"{INFO}: [{error_prefix}] Check guardrails request resolved."
+ CHECK_GUARDRAILS_SUCCESS = f"{INFO}: [{error_prefix}] Guardrails checked."
+ POLL_RUN_STARTED = f"{INFO}: [{error_prefix}] Polling detect run {{}} with wait time {{}} seconds and max attempts {{}}."
+ POLL_RUN_TERMINAL = f"{INFO}: [{error_prefix}] Detect run reached a terminal status."
+ POLL_RUN_BUDGET_EXHAUSTED = f"{INFO}: [{error_prefix}] Detect run polling budget exhausted."
+
class ErrorLogs(Enum):
INVALID_LOG_LEVEL = f"{ERROR}: [{error_prefix}] Invalid log level. Specify a valid log level."
INVALID_KEY = f"{ERROR}: [{error_prefix}] Invalid key {{}} in config."
@@ -415,6 +480,15 @@ class ErrorLogs(Enum):
DETECT_FILE_REQUEST_REJECTED = f"{ERROR}: [{error_prefix}] Deidentify file resulted in failure."
EMPTY_FILE_COLUMN_NAME = f"{ERROR}: [{error_prefix}] Empty column name in FILE_UPLOAD"
+ DEIDENTIFY_STRING_REQUEST_REJECTED = f"{ERROR}: [{error_prefix}] Deidentify string resulted in failure."
+ REIDENTIFY_STRING_REQUEST_REJECTED = f"{ERROR}: [{error_prefix}] Reidentify string resulted in failure."
+ DEIDENTIFY_FILE_V2_REQUEST_REJECTED = f"{ERROR}: [{error_prefix}] Deidentify file resulted in failure."
+ REIDENTIFY_FILE_REQUEST_REJECTED = f"{ERROR}: [{error_prefix}] Reidentify file resulted in failure."
+ GET_RUN_REQUEST_REJECTED = f"{ERROR}: [{error_prefix}] Get run resulted in failure."
+ CHECK_GUARDRAILS_REQUEST_REJECTED = f"{ERROR}: [{error_prefix}] Check guardrails resulted in failure."
+ FAILED_TO_ENCODE_FILE_IN_DEIDENTIFY_FILE = f"{ERROR}: [{error_prefix}] Failed to encode the file in deidentify file."
+ FAILED_TO_WRITE_OUTPUT_FILE = f"{ERROR}: [{error_prefix}] Failed to write the processed output to disk."
+
class Interface(Enum):
INSERT = "INSERT"
GET = "GET"
diff --git a/common/utils/enums/detect.py b/common/utils/enums/detect.py
new file mode 100644
index 00000000..abcb0689
--- /dev/null
+++ b/common/utils/enums/detect.py
@@ -0,0 +1,164 @@
+from enum import Enum
+
+
+class EntityType(Enum):
+ NONE = "NONE"
+ ACCOUNT_NUMBER = "ACCOUNT_NUMBER"
+ AGE = "AGE"
+ ALL = "ALL"
+ BANK_ACCOUNT = "BANK_ACCOUNT"
+ BLOOD_TYPE = "BLOOD_TYPE"
+ CONDITION = "CONDITION"
+ CORPORATE_ACTION = "CORPORATE_ACTION"
+ CREDIT_CARD = "CREDIT_CARD"
+ CREDIT_CARD_EXPIRATION = "CREDIT_CARD_EXPIRATION"
+ CVV = "CVV"
+ DATE = "DATE"
+ DATE_INTERVAL = "DATE_INTERVAL"
+ DAY = "DAY"
+ DOB = "DOB"
+ DOSE = "DOSE"
+ DRIVER_LICENSE = "DRIVER_LICENSE"
+ DRUG = "DRUG"
+ DURATION = "DURATION"
+ EFFECT = "EFFECT"
+ EMAIL_ADDRESS = "EMAIL_ADDRESS"
+ EVENT = "EVENT"
+ FILENAME = "FILENAME"
+ FINANCIAL_METRIC = "FINANCIAL_METRIC"
+ GENDER = "GENDER"
+ HEALTHCARE_NUMBER = "HEALTHCARE_NUMBER"
+ INJURY = "INJURY"
+ IP_ADDRESS = "IP_ADDRESS"
+ LANGUAGE = "LANGUAGE"
+ LOCATION = "LOCATION"
+ LOCATION_ADDRESS = "LOCATION_ADDRESS"
+ LOCATION_ADDRESS_STREET = "LOCATION_ADDRESS_STREET"
+ LOCATION_CITY = "LOCATION_CITY"
+ LOCATION_COORDINATE = "LOCATION_COORDINATE"
+ LOCATION_COUNTRY = "LOCATION_COUNTRY"
+ LOCATION_STATE = "LOCATION_STATE"
+ LOCATION_ZIP = "LOCATION_ZIP"
+ MARITAL_STATUS = "MARITAL_STATUS"
+ MEDICAL_CODE = "MEDICAL_CODE"
+ MEDICAL_PROCESS = "MEDICAL_PROCESS"
+ MONEY = "MONEY"
+ MONTH = "MONTH"
+ NAME = "NAME"
+ NAME_FAMILY = "NAME_FAMILY"
+ NAME_GIVEN = "NAME_GIVEN"
+ NAME_MEDICAL_PROFESSIONAL = "NAME_MEDICAL_PROFESSIONAL"
+ NUMERICAL_PII = "NUMERICAL_PII"
+ OCCUPATION = "OCCUPATION"
+ ORGANIZATION = "ORGANIZATION"
+ ORGANIZATION_ID = "ORGANIZATION_ID"
+ ORGANIZATION_MEDICAL_FACILITY = "ORGANIZATION_MEDICAL_FACILITY"
+ ORIGIN = "ORIGIN"
+ PASSPORT_NUMBER = "PASSPORT_NUMBER"
+ PASSWORD = "PASSWORD"
+ PHONE_NUMBER = "PHONE_NUMBER"
+ PHYSICAL_ATTRIBUTE = "PHYSICAL_ATTRIBUTE"
+ POLITICAL_AFFILIATION = "POLITICAL_AFFILIATION"
+ PRODUCT = "PRODUCT"
+ PROJECT = "PROJECT"
+ RELIGION = "RELIGION"
+ ROUTING_NUMBER = "ROUTING_NUMBER"
+ SEXUALITY = "SEXUALITY"
+ SSN = "SSN"
+ STATISTICS = "STATISTICS"
+ TIME = "TIME"
+ TREND = "TREND"
+ URL = "URL"
+ USERNAME = "USERNAME"
+ VEHICLE_ID = "VEHICLE_ID"
+ YEAR = "YEAR"
+ ZODIAC_SIGN = "ZODIAC_SIGN"
+
+
+class DeidentificationType(Enum):
+ UNKNOWN = "UNKNOWN"
+ ENTITY_UNIQUE_COUNTER = "ENTITY_UNIQUE_COUNTER"
+ ENTITY_ONLY = "ENTITY_ONLY"
+ VAULT_TOKEN = "VAULT_TOKEN"
+ MASK = "MASK"
+
+
+class ReturnEntitiesType(Enum):
+ EXCLUDE_SENSITIVE_DATA = "EXCLUDE_SENSITIVE_DATA"
+ ALL = "ALL"
+ NONE = "NONE"
+
+
+class FileDataFormat(Enum):
+ BMP = "bmp"
+ CSV = "csv"
+ DCM = "dcm"
+ DOC = "doc"
+ DOCX = "docx"
+ GIF = "gif"
+ JPEG = "jpeg"
+ JPG = "jpg"
+ JSON = "json"
+ JSONL = "jsonl"
+ MP3 = "mp3"
+ PDF = "pdf"
+ PNG = "png"
+ PPT = "ppt"
+ PPTX = "pptx"
+ TIF = "tif"
+ TIFF = "tiff"
+ TXT = "txt"
+ WAV = "wav"
+ XLS = "xls"
+ XLSX = "xlsx"
+ XML = "xml"
+ ZIP = "zip"
+
+
+class DetectRunStatus(Enum):
+ UNKNOWN = "UNKNOWN"
+ QUEUED = "QUEUED"
+ IN_PROGRESS = "IN_PROGRESS"
+ SUCCESS = "SUCCESS"
+ FAILED = "FAILED"
+
+
+class ObjectEntityType(Enum):
+ NONE = "NONE"
+ FACE = "FACE"
+ LICENSE_PLATE = "LICENSE_PLATE"
+ LOGO = "LOGO"
+ SIGNATURE = "SIGNATURE"
+ ALL = "ALL"
+
+
+class ObjectDeidentificationType(Enum):
+ UNKNOWN = "UNKNOWN"
+ REDACT = "REDACT"
+ UNREDACT = "UNREDACT"
+
+
+class OutputTranscriptionType(Enum):
+ NONE = "NONE"
+ TRANSCRIPTION = "TRANSCRIPTION"
+ MEDICAL_TRANSCRIPTION = "MEDICAL_TRANSCRIPTION"
+ DIARIZED_TRANSCRIPTION = "DIARIZED_TRANSCRIPTION"
+ MEDICAL_DIARIZED_TRANSCRIPTION = "MEDICAL_DIARIZED_TRANSCRIPTION"
+
+
+class PdfProcessingMode(Enum):
+ NONE = "NONE"
+ OCR = "OCR"
+ TEXT_LAYER = "TEXT_LAYER"
+
+
+class MaskingMethod(Enum):
+ NONE = "NONE"
+ BLUR = "BLUR"
+ BLACKBOX = "BLACKBOX"
+
+
+class GuardrailsValidation(Enum):
+ PASSED = "PASSED"
+ FAILED = "FAILED"
+ UNKNOWN = "UNKNOWN"
diff --git a/common/vault/detect/__init__.py b/common/vault/detect/__init__.py
new file mode 100644
index 00000000..ae8b5470
--- /dev/null
+++ b/common/vault/detect/__init__.py
@@ -0,0 +1,71 @@
+from ._controller import DetectController
+from ._models import (
+ Audio,
+ Bleep,
+ CheckGuardrailsRequest,
+ CheckGuardrailsResponse,
+ CustomType,
+ DeidentifyFileRequest,
+ DeidentifyFileResponse,
+ DeidentifyStringRequest,
+ DeidentifyStringResponse,
+ Detect,
+ DetectConfiguration,
+ DetectedEntity,
+ Document,
+ Entity,
+ EntityLocation,
+ FileMapping,
+ FileOutput,
+ GetRunRequest,
+ GetRunResponse,
+ Image,
+ Media,
+ Metrics,
+ ObjectEntity,
+ Pdf,
+ PollOptions,
+ RedactionRule,
+ ReidentifyFileRequest,
+ ReidentifyFileResponse,
+ ReidentifyStringRequest,
+ ReidentifyStringResponse,
+ ShiftDates,
+ Transformation,
+)
+
+__all__ = [
+ "DetectController",
+ "Audio",
+ "Bleep",
+ "CheckGuardrailsRequest",
+ "CheckGuardrailsResponse",
+ "CustomType",
+ "DeidentifyFileRequest",
+ "DeidentifyFileResponse",
+ "DeidentifyStringRequest",
+ "DeidentifyStringResponse",
+ "Detect",
+ "DetectConfiguration",
+ "DetectedEntity",
+ "Document",
+ "Entity",
+ "EntityLocation",
+ "FileMapping",
+ "FileOutput",
+ "GetRunRequest",
+ "GetRunResponse",
+ "Image",
+ "Media",
+ "Metrics",
+ "ObjectEntity",
+ "Pdf",
+ "PollOptions",
+ "RedactionRule",
+ "ReidentifyFileRequest",
+ "ReidentifyFileResponse",
+ "ReidentifyStringRequest",
+ "ReidentifyStringResponse",
+ "ShiftDates",
+ "Transformation",
+]
diff --git a/common/vault/detect/_constants.py b/common/vault/detect/_constants.py
new file mode 100644
index 00000000..12c351fc
--- /dev/null
+++ b/common/vault/detect/_constants.py
@@ -0,0 +1,36 @@
+DEFAULT_WAIT_TIME_SECONDS = 60
+MAX_WAIT_TIME_SECONDS = 300
+DEFAULT_MAX_ATTEMPTS = 23
+MAX_MAX_ATTEMPTS = 23
+MIN_WAIT_TIME_SECONDS = 1
+MIN_MAX_ATTEMPTS = 1
+INITIAL_DELAY_SECONDS = 1
+MAX_DELAY_SECONDS = 32
+DELAY_MULTIPLIER = 2
+SECONDS_TO_MILLIS = 1000
+
+AUTHORIZATION_HEADER = "Authorization"
+BEARER_PREFIX = "Bearer "
+REQUEST_ID_HEADER = "x-request-id"
+ADDITIONAL_HEADERS_KEY = "additional_headers"
+VAULT_ID_PARAM = "vault_id"
+
+ENCODING_UTF_8 = "utf-8"
+DATA_SOURCE_BASE64 = "BASE64"
+EXTENSION_SEPARATOR = "."
+PROCESSED_FILE_PREFIX = "processed-"
+ENTITIES_TYPE_TOKEN = "ENTITIES"
+ENTITIES_EXTENSION = "json"
+BINARY_EXTENSION = "bin"
+DEFAULT_OUTPUT_BASE_NAME = "output"
+UNDERSCORE = "_"
+DASH = "-"
+
+ERROR_BODY_KEY = "error"
+ERROR_MESSAGE_KEY = "message"
+ERROR_GRPC_CODE_KEY = "grpc_code"
+ERROR_GRPC_CODE_CAMEL_KEY = "grpcCode"
+ERROR_HTTP_STATUS_KEY = "http_status"
+ERROR_HTTP_STATUS_CAMEL_KEY = "httpStatus"
+ERROR_DETAILS_KEY = "details"
+UNKNOWN_ERROR_MESSAGE = "Unknown error"
diff --git a/common/vault/detect/_controller.py b/common/vault/detect/_controller.py
new file mode 100644
index 00000000..777d221b
--- /dev/null
+++ b/common/vault/detect/_controller.py
@@ -0,0 +1,226 @@
+import base64
+import json
+
+from common.errors import SkyflowError
+from common.utils import SkyflowMessages
+from common.utils.constants import SKY_META_DATA_HEADER
+from common.utils.logger import log_info, log_error_log
+
+from . import _mappers as mappers
+from ._constants import (
+ ADDITIONAL_HEADERS_KEY,
+ AUTHORIZATION_HEADER,
+ BEARER_PREFIX,
+ DATA_SOURCE_BASE64,
+ ENCODING_UTF_8,
+ VAULT_ID_PARAM,
+)
+from ._errors import to_skyflow_error
+from ._file_flow import complete_deidentify_file
+from ._models import GetRunRequest
+from ._validations import (
+ validate_check_guardrails_request,
+ validate_deidentify_file_request,
+ validate_deidentify_string_request,
+ validate_get_run_request,
+ validate_reidentify_file_request,
+ validate_reidentify_string_request,
+)
+
+
+class DetectController:
+ def __init__(self, vault_client):
+ self._vault_client = vault_client
+
+ def deidentify_string(self, request):
+ log_info(SkyflowMessages.Info.DEIDENTIFY_STRING_TRIGGERED.value, self._vault_client.get_logger())
+ log_info(SkyflowMessages.Info.VALIDATE_DEIDENTIFY_STRING_REQUEST.value, self._vault_client.get_logger())
+ validate_deidentify_string_request(request)
+ self._vault_client.initialize_client_configuration()
+ kwargs = self.__omit_none(
+ text=request.text,
+ configuration_id=request.configuration_id,
+ configuration=self.__configuration(request.configuration),
+ )
+ try:
+ raw = self._vault_client.get_strings_v2_api().with_raw_response.deidentify_string_v2(
+ request_options=self.__request_options(), **kwargs,
+ )
+ log_info(SkyflowMessages.Info.DEIDENTIFY_STRING_REQUEST_RESOLVED.value, self._vault_client.get_logger())
+ response = mappers.to_deidentify_string_response(raw.data)
+ log_info(SkyflowMessages.Info.DEIDENTIFY_STRING_SUCCESS.value, self._vault_client.get_logger())
+ return response
+ except Exception as e:
+ log_error_log(SkyflowMessages.ErrorLogs.DEIDENTIFY_STRING_REQUEST_REJECTED.value, self._vault_client.get_logger())
+ raise to_skyflow_error(e)
+
+ def reidentify_string(self, request):
+ log_info(SkyflowMessages.Info.REIDENTIFY_STRING_TRIGGERED.value, self._vault_client.get_logger())
+ log_info(SkyflowMessages.Info.VALIDATE_REIDENTIFY_STRING_REQUEST.value, self._vault_client.get_logger())
+ validate_reidentify_string_request(request)
+ self._vault_client.initialize_client_configuration()
+ kwargs = self.__omit_none(
+ redaction_level=self.__redaction_levels(request.redaction_level),
+ )
+ try:
+ raw = self._vault_client.get_strings_v2_api().with_raw_response.reidentify_string_v2(
+ vault_id=self._vault_client.get_vault_id(),
+ text=request.text,
+ request_options=self.__request_options(),
+ **kwargs,
+ )
+ log_info(SkyflowMessages.Info.REIDENTIFY_STRING_REQUEST_RESOLVED.value, self._vault_client.get_logger())
+ response = mappers.to_reidentify_string_response(raw.data)
+ log_info(SkyflowMessages.Info.REIDENTIFY_STRING_SUCCESS.value, self._vault_client.get_logger())
+ return response
+ except Exception as e:
+ log_error_log(SkyflowMessages.ErrorLogs.REIDENTIFY_STRING_REQUEST_REJECTED.value, self._vault_client.get_logger())
+ raise to_skyflow_error(e)
+
+ def deidentify_file(self, request):
+ log_info(SkyflowMessages.Info.DEIDENTIFY_FILE_V2_TRIGGERED.value, self._vault_client.get_logger())
+ log_info(SkyflowMessages.Info.VALIDATE_DEIDENTIFY_FILE_REQUEST.value, self._vault_client.get_logger())
+ validate_deidentify_file_request(request)
+ self._vault_client.initialize_client_configuration()
+ data_source, value, data_format = self.__resolve_file_input(request)
+ kwargs = self.__omit_none(
+ data_format=data_format,
+ configuration_id=request.configuration_id,
+ configuration=self.__configuration(request.configuration),
+ )
+ try:
+ raw = self._vault_client.get_files_v2_api().with_raw_response.deidentify_file_v2(
+ data_source=data_source,
+ value=value,
+ request_options=self.__request_options(),
+ **kwargs,
+ )
+ log_info(SkyflowMessages.Info.DEIDENTIFY_FILE_V2_REQUEST_RESOLVED.value, self._vault_client.get_logger())
+ run_id = raw.data.run_id
+ except Exception as e:
+ log_error_log(SkyflowMessages.ErrorLogs.DEIDENTIFY_FILE_V2_REQUEST_REJECTED.value, self._vault_client.get_logger())
+ raise to_skyflow_error(e)
+
+ response = complete_deidentify_file(
+ request, run_id, self.__poll_fetcher, logger=self._vault_client.get_logger(),
+ )
+ log_info(SkyflowMessages.Info.DEIDENTIFY_FILE_V2_SUCCESS.value, self._vault_client.get_logger())
+ return response
+
+ def reidentify_file(self, request):
+ log_info(SkyflowMessages.Info.REIDENTIFY_FILE_TRIGGERED.value, self._vault_client.get_logger())
+ log_info(SkyflowMessages.Info.VALIDATE_REIDENTIFY_FILE_REQUEST.value, self._vault_client.get_logger())
+ validate_reidentify_file_request(request)
+ self._vault_client.initialize_client_configuration()
+ kwargs = self.__omit_none(
+ data_format=request.data_format.value if request.data_format is not None else None,
+ redaction_level=self.__redaction_levels(request.redaction_level),
+ )
+ try:
+ raw = self._vault_client.get_files_v2_api().with_raw_response.reidentify_file_v2(
+ data_source=request.data_source.value,
+ value=request.value,
+ vault_id=self._vault_client.get_vault_id(),
+ request_options=self.__request_options(),
+ **kwargs,
+ )
+ log_info(SkyflowMessages.Info.REIDENTIFY_FILE_REQUEST_RESOLVED.value, self._vault_client.get_logger())
+ response = mappers.to_reidentify_file_response(raw.data, self._vault_client.get_reidentify_source_type())
+ log_info(SkyflowMessages.Info.REIDENTIFY_FILE_SUCCESS.value, self._vault_client.get_logger())
+ return response
+ except Exception as e:
+ log_error_log(SkyflowMessages.ErrorLogs.REIDENTIFY_FILE_REQUEST_REJECTED.value, self._vault_client.get_logger())
+ raise to_skyflow_error(e)
+
+ def get_run(self, request):
+ log_info(SkyflowMessages.Info.GET_RUN_TRIGGERED.value, self._vault_client.get_logger())
+ log_info(SkyflowMessages.Info.VALIDATE_GET_RUN_REQUEST.value, self._vault_client.get_logger())
+ validate_get_run_request(request)
+ self._vault_client.initialize_client_configuration()
+ run_id = request.run_id.strip()
+ try:
+ raw = self._vault_client.get_files_v2_api().with_raw_response.get_run_v2(
+ run_id,
+ vault_id=self._vault_client.get_vault_id(),
+ request_options=self.__request_options(),
+ )
+ log_info(SkyflowMessages.Info.GET_RUN_REQUEST_RESOLVED.value, self._vault_client.get_logger())
+ response = mappers.to_get_run_response(run_id, raw.data, self._vault_client.get_deidentify_source_type())
+ log_info(SkyflowMessages.Info.GET_RUN_SUCCESS.value, self._vault_client.get_logger())
+ return response
+ except Exception as e:
+ log_error_log(SkyflowMessages.ErrorLogs.GET_RUN_REQUEST_REJECTED.value, self._vault_client.get_logger())
+ raise to_skyflow_error(e)
+
+ def check_guardrails(self, request):
+ log_info(SkyflowMessages.Info.CHECK_GUARDRAILS_TRIGGERED.value, self._vault_client.get_logger())
+ log_info(SkyflowMessages.Info.VALIDATE_CHECK_GUARDRAILS_REQUEST.value, self._vault_client.get_logger())
+ validate_check_guardrails_request(request)
+ self._vault_client.initialize_client_configuration()
+ kwargs = self.__omit_none(
+ check_toxicity=request.check_toxicity,
+ deny_topics=request.deny_topics,
+ )
+ try:
+ raw = self._vault_client.get_guardrails_v2_api().with_raw_response.check_guardrails_v2(
+ text=request.text,
+ vault_id=self._vault_client.get_vault_id(),
+ request_options=self.__request_options(),
+ **kwargs,
+ )
+ log_info(SkyflowMessages.Info.CHECK_GUARDRAILS_REQUEST_RESOLVED.value, self._vault_client.get_logger())
+ response = mappers.to_check_guardrails_response(raw.data)
+ log_info(SkyflowMessages.Info.CHECK_GUARDRAILS_SUCCESS.value, self._vault_client.get_logger())
+ return response
+ except Exception as e:
+ log_error_log(SkyflowMessages.ErrorLogs.CHECK_GUARDRAILS_REQUEST_REJECTED.value, self._vault_client.get_logger())
+ raise to_skyflow_error(e)
+
+ def __poll_fetcher(self, run_id):
+ return self.get_run(GetRunRequest(run_id=run_id))
+
+ def __configuration(self, configuration):
+ if configuration is None:
+ return None
+ return mappers.to_detect_config(configuration, self._vault_client.get_vault_id())
+
+ def __redaction_levels(self, redaction_level):
+ if redaction_level is None:
+ return None
+ return mappers.to_redaction_levels(redaction_level)
+
+ def __resolve_file_input(self, request):
+ if request.file_path is not None or request.file is not None:
+ content, name = self.__read_file(request)
+ value = base64.b64encode(content).decode(ENCODING_UTF_8)
+ data_source = DATA_SOURCE_BASE64
+ data_format = request.data_format if request.data_format is not None else mappers.infer_format(name)
+ return data_source, value, data_format.value if data_format is not None else None
+ data_source = request.data_source.value if request.data_source is not None else None
+ data_format = request.data_format.value if request.data_format is not None else None
+ return data_source, request.value, data_format
+
+ def __read_file(self, request):
+ try:
+ if request.file_path is not None:
+ with open(request.file_path, "rb") as handle:
+ return handle.read(), request.file_path
+ return request.file.read(), getattr(request.file, "name", None)
+ except (OSError, ValueError):
+ raise SkyflowError(
+ SkyflowMessages.Error.FAILED_TO_ENCODE_FILE.value,
+ SkyflowMessages.ErrorCodes.INVALID_INPUT.value,
+ )
+
+ def __headers(self):
+ headers = {SKY_META_DATA_HEADER: json.dumps(self._vault_client.get_sdk_metrics())}
+ token = self._vault_client.get_current_bearer_token()
+ if token:
+ headers[AUTHORIZATION_HEADER] = BEARER_PREFIX + token
+ return headers
+
+ def __request_options(self):
+ return {ADDITIONAL_HEADERS_KEY: self.__headers()}
+
+ def __omit_none(self, **kwargs):
+ return {key: value for key, value in kwargs.items() if value is not None}
diff --git a/common/vault/detect/_errors.py b/common/vault/detect/_errors.py
new file mode 100644
index 00000000..4a2e54a9
--- /dev/null
+++ b/common/vault/detect/_errors.py
@@ -0,0 +1,61 @@
+from common.errors import SkyflowError
+from common.utils import SkyflowMessages as CommonMessages
+from common.generated.rest.core import ApiError, ParsingError
+
+from ._constants import (
+ REQUEST_ID_HEADER,
+ ERROR_BODY_KEY,
+ ERROR_MESSAGE_KEY,
+ ERROR_GRPC_CODE_KEY,
+ ERROR_GRPC_CODE_CAMEL_KEY,
+ ERROR_HTTP_STATUS_KEY,
+ ERROR_HTTP_STATUS_CAMEL_KEY,
+ ERROR_DETAILS_KEY,
+ UNKNOWN_ERROR_MESSAGE,
+)
+
+
+def extract_request_id(headers):
+ return headers.get(REQUEST_ID_HEADER) if headers else None
+
+
+def to_skyflow_error(e):
+ if isinstance(e, SkyflowError):
+ return e
+ if isinstance(e, (ApiError, ParsingError)):
+ message, grpc_code, http_status, details = _parse_api_error_body(e.body)
+ return SkyflowError(
+ message=message,
+ http_code=e.status_code,
+ request_id=extract_request_id(e.headers),
+ grpc_code=grpc_code,
+ http_status=http_status,
+ details=details,
+ )
+ return SkyflowError(
+ message=str(e) if e else CommonMessages.Error.GENERIC_API_ERROR.value,
+ http_code=None,
+ )
+
+
+def _parse_api_error_body(body):
+ error = getattr(body, ERROR_BODY_KEY, None) if body is not None and not isinstance(body, dict) else None
+ if error is not None and not isinstance(error, dict):
+ return (
+ getattr(error, ERROR_MESSAGE_KEY, None) or UNKNOWN_ERROR_MESSAGE,
+ getattr(error, ERROR_GRPC_CODE_KEY, None),
+ getattr(error, ERROR_HTTP_STATUS_KEY, None),
+ getattr(error, ERROR_DETAILS_KEY, None) or [],
+ )
+ if isinstance(body, dict):
+ error = body.get(ERROR_BODY_KEY)
+ if isinstance(error, dict):
+ return (
+ error.get(ERROR_MESSAGE_KEY) or UNKNOWN_ERROR_MESSAGE,
+ error.get(ERROR_GRPC_CODE_KEY, error.get(ERROR_GRPC_CODE_CAMEL_KEY)),
+ error.get(ERROR_HTTP_STATUS_KEY, error.get(ERROR_HTTP_STATUS_CAMEL_KEY)),
+ error.get(ERROR_DETAILS_KEY) or [],
+ )
+ if error is not None:
+ return (str(error), None, None, [])
+ return (UNKNOWN_ERROR_MESSAGE, None, None, [])
diff --git a/common/vault/detect/_file_flow.py b/common/vault/detect/_file_flow.py
new file mode 100644
index 00000000..bcb4593e
--- /dev/null
+++ b/common/vault/detect/_file_flow.py
@@ -0,0 +1,21 @@
+import time
+
+from common.utils.enums.detect import DetectRunStatus
+
+from ._file_output_writer import write_outputs
+from ._mappers import submitted_deidentify_file_response, to_deidentify_file_response
+from ._polling import poll_run
+
+
+def complete_deidentify_file(request, run_id, fetcher, logger=None, sleeper=time.sleep):
+ if request.poll_options is None or run_id is None:
+ return submitted_deidentify_file_response(run_id)
+
+ run = poll_run(run_id, request.poll_options, fetcher, logger=logger, sleeper=sleeper)
+ response = to_deidentify_file_response(run_id, run)
+
+ if response.status == DetectRunStatus.SUCCESS and (request.file is not None or request.file_path is not None):
+ input_name = request.file_path if request.file_path is not None else getattr(request.file, "name", None)
+ write_outputs(response.output, response.output_type, input_name, request.output_directory)
+
+ return response
diff --git a/common/vault/detect/_file_output_writer.py b/common/vault/detect/_file_output_writer.py
new file mode 100644
index 00000000..88ad22a9
--- /dev/null
+++ b/common/vault/detect/_file_output_writer.py
@@ -0,0 +1,89 @@
+import base64
+import os
+
+from common.errors import SkyflowError
+from common.utils import SkyflowMessages
+
+from ._constants import (
+ DATA_SOURCE_BASE64,
+ PROCESSED_FILE_PREFIX,
+ ENTITIES_TYPE_TOKEN,
+ ENTITIES_EXTENSION,
+ BINARY_EXTENSION,
+ DEFAULT_OUTPUT_BASE_NAME,
+ EXTENSION_SEPARATOR,
+ UNDERSCORE,
+ DASH,
+)
+
+
+def write_outputs(outputs, output_type, input_file_name, output_directory):
+ if not outputs:
+ return []
+ if output_type is None or output_type.value != DATA_SOURCE_BASE64:
+ return []
+
+ directory = None
+ if output_directory and output_directory.strip():
+ directory = output_directory
+ if not os.path.isdir(directory):
+ try:
+ os.makedirs(directory, exist_ok=True)
+ except OSError:
+ raise SkyflowError(
+ SkyflowMessages.Error.FAILED_TO_WRITE_OUTPUT_FILE.value.format(directory),
+ None,
+ )
+
+ base = _strip_extension(input_file_name)
+ used = set()
+ written = []
+ for output in outputs:
+ if output.processed_file is None:
+ continue
+ name = _file_name(base, output, used)
+ used.add(name)
+ target = name if directory is None else os.path.join(directory, name)
+ try:
+ data = base64.b64decode(output.processed_file)
+ with open(target, "wb") as handle:
+ handle.write(data)
+ except (ValueError, OSError):
+ raise SkyflowError(
+ SkyflowMessages.Error.FAILED_TO_WRITE_OUTPUT_FILE.value.format(target),
+ None,
+ )
+ written.append(target)
+ return written
+
+
+def _strip_extension(file_name):
+ if not file_name:
+ return DEFAULT_OUTPUT_BASE_NAME
+ base = os.path.basename(file_name)
+ dot = base.rfind(EXTENSION_SEPARATOR)
+ if dot > 0:
+ base = base[:dot]
+ return base or DEFAULT_OUTPUT_BASE_NAME
+
+
+def _file_name(base, output, used):
+ file_type = output.processed_file_type or ""
+ is_entities = ENTITIES_TYPE_TOKEN in file_type.upper()
+ if output.processed_file_extension is not None:
+ extension = output.processed_file_extension.value
+ elif is_entities:
+ extension = ENTITIES_EXTENSION
+ else:
+ extension = BINARY_EXTENSION
+
+ if is_entities:
+ stem = PROCESSED_FILE_PREFIX + file_type.lower().replace(UNDERSCORE, DASH) + DASH + base
+ else:
+ stem = PROCESSED_FILE_PREFIX + base
+
+ name = stem + EXTENSION_SEPARATOR + extension
+ if name in used:
+ disambiguator = str(len(used)) if file_type == "" else file_type.lower()
+ name = stem + EXTENSION_SEPARATOR + disambiguator + EXTENSION_SEPARATOR + extension
+ return name
diff --git a/common/vault/detect/_mappers.py b/common/vault/detect/_mappers.py
new file mode 100644
index 00000000..cdf0f163
--- /dev/null
+++ b/common/vault/detect/_mappers.py
@@ -0,0 +1,293 @@
+from common.generated.rest.types import (
+ DetectConfigV2 as WireDetectConfigV2,
+ Detect as WireDetect,
+ DetectEntity as WireDetectEntity,
+ EntityTransformation as WireEntityTransformation,
+ TransformationShiftDates as WireTransformationShiftDates,
+ DetectCustomTypes as WireDetectCustomTypes,
+ DetectObjectEntity as WireDetectObjectEntity,
+ FileMapping as WireFileMapping,
+ Media as WireMedia,
+ AudioV2 as WireAudioV2,
+ AudioV2Bleep as WireAudioV2Bleep,
+ DocumentV2 as WireDocumentV2,
+ DocumentV2Pdf as WireDocumentV2Pdf,
+ ImageV2 as WireImageV2,
+ RedactionLevel as WireRedactionLevel,
+)
+from common.utils.enums.detect import (
+ DetectRunStatus,
+ FileDataFormat,
+ GuardrailsValidation,
+)
+
+from ._constants import EXTENSION_SEPARATOR
+from ._models import (
+ CheckGuardrailsResponse,
+ DeidentifyFileResponse,
+ DeidentifyStringResponse,
+ DetectedEntity,
+ EntityLocation,
+ FileOutput,
+ GetRunResponse,
+ Metrics,
+ ReidentifyFileResponse,
+ ReidentifyStringResponse,
+)
+
+
+def _omit_none(**kwargs):
+ return {key: value for key, value in kwargs.items() if value is not None}
+
+
+def _enum_value(member):
+ return member.value if member is not None else None
+
+
+def _enum_or_default(enum_cls, value, fallback):
+ if value is None:
+ return fallback
+ try:
+ return enum_cls(str(value))
+ except ValueError:
+ return fallback
+
+
+def infer_format(file_name):
+ if not file_name:
+ return None
+ index = file_name.rfind(EXTENSION_SEPARATOR)
+ if index < 0 or index == len(file_name) - 1:
+ return None
+ try:
+ return FileDataFormat[file_name[index + 1:].upper()]
+ except KeyError:
+ return None
+
+
+def to_detect_config(configuration, vault_id):
+ return WireDetectConfigV2(
+ vault_id=vault_id,
+ **_omit_none(
+ name=configuration.name,
+ description=configuration.description,
+ detect=to_detect(configuration.detect) if configuration.detect is not None else None,
+ file_mapping=to_file_mappings(configuration.file_mapping) if configuration.file_mapping is not None else None,
+ media=to_media(configuration.media) if configuration.media is not None else None,
+ ),
+ )
+
+
+def to_detect(detect):
+ return WireDetect(**_omit_none(
+ entities=[to_entity(entity) for entity in detect.entities if entity is not None] if detect.entities is not None else None,
+ object_entities=[to_object_entity(obj) for obj in detect.object_entities if obj is not None] if detect.object_entities is not None else None,
+ restrict=detect.restrict,
+ skip=detect.skip,
+ custom_types=[to_custom_type(custom) for custom in detect.custom_types if custom is not None] if detect.custom_types is not None else None,
+ return_entities=_enum_value(detect.return_entities),
+ ))
+
+
+def to_entity(entity):
+ return WireDetectEntity(**_omit_none(
+ entity_type=_enum_value(entity.entity_type),
+ deidentification_type=_enum_value(entity.deidentification_type),
+ destination=entity.destination,
+ transformation=to_transformation(entity.transformation) if entity.transformation is not None else None,
+ ))
+
+
+def to_transformation(transformation):
+ shift_dates = transformation.shift_dates
+ if shift_dates is None:
+ return WireEntityTransformation()
+ return WireEntityTransformation(shift_dates=WireTransformationShiftDates(**_omit_none(
+ min_days=shift_dates.min_days,
+ max_days=shift_dates.max_days,
+ )))
+
+
+def to_custom_type(custom_type):
+ return WireDetectCustomTypes(**_omit_none(
+ label=custom_type.label,
+ match=custom_type.match,
+ ))
+
+
+def to_object_entity(object_entity):
+ return WireDetectObjectEntity(**_omit_none(
+ entity_type=_enum_value(object_entity.entity_type),
+ deidentification_type=_enum_value(object_entity.deidentification_type),
+ ))
+
+
+def to_file_mappings(file_mappings):
+ result = []
+ for mapping in file_mappings:
+ if mapping is None:
+ continue
+ result.append(WireFileMapping(**_omit_none(
+ source=mapping.source,
+ destination=mapping.destination,
+ output_file_name_suffix=mapping.output_file_name_suffix,
+ entities_destination=mapping.entities_destination,
+ object_entities_destination=mapping.object_entities_destination,
+ )))
+ return result
+
+
+def to_media(media):
+ return WireMedia(**_omit_none(
+ audio=to_audio(media.audio) if media.audio is not None else None,
+ document=to_document(media.document) if media.document is not None else None,
+ image=to_image(media.image) if media.image is not None else None,
+ ))
+
+
+def to_audio(audio):
+ bleep = audio.bleep
+ return WireAudioV2(**_omit_none(
+ output_processed_audio=audio.output_processed_audio,
+ output_transcription=_enum_value(audio.output_transcription),
+ bleep=WireAudioV2Bleep(**_omit_none(
+ start_padding=bleep.start_padding,
+ stop_padding=bleep.stop_padding,
+ frequency=bleep.frequency,
+ gain=bleep.gain,
+ )) if bleep is not None else None,
+ ))
+
+
+def to_document(document):
+ pdf = document.pdf
+ return WireDocumentV2(**_omit_none(
+ pdf=WireDocumentV2Pdf(**_omit_none(
+ processing_mode=_enum_value(pdf.processing_mode),
+ density=pdf.density,
+ max_resolution=pdf.max_resolution,
+ )) if pdf is not None else None,
+ ))
+
+
+def to_image(image):
+ return WireImageV2(**_omit_none(
+ output_processed_image=image.output_processed_image,
+ output_ocr_text=image.output_ocr_text,
+ masking_method=_enum_value(image.masking_method),
+ ))
+
+
+def to_redaction_levels(levels):
+ result = []
+ for level in levels:
+ if level is None:
+ continue
+ result.append(WireRedactionLevel(**_omit_none(
+ entity_name=_enum_value(level._api_entity_name()),
+ redaction_type=_enum_value(level._api_redaction_type()),
+ token_group_name=level._api_token_group_name(),
+ redaction_pattern=level._api_redaction_pattern(),
+ )))
+ return result
+
+
+def to_metrics(metrics):
+ return Metrics(
+ size=metrics.size,
+ word_count=metrics.word_count,
+ character_count=metrics.character_count,
+ slides=metrics.slides,
+ pages=metrics.pages,
+ duration=metrics.duration,
+ )
+
+
+def to_file_output(api_output):
+ return FileOutput(
+ processed_file=api_output.processed_file,
+ processed_file_type=api_output.processed_file_type,
+ processed_file_extension=_enum_or_default(FileDataFormat, api_output.processed_file_extension, None),
+ )
+
+
+def to_entity_location(location):
+ return EntityLocation(
+ start_index=location.start_index,
+ end_index=location.end_index,
+ start_index_processed=location.start_index_processed,
+ end_index_processed=location.end_index_processed,
+ )
+
+
+def to_detected_entity(api_entity):
+ scores = api_entity.entity_scores
+ return DetectedEntity(
+ token=api_entity.token,
+ value=api_entity.value,
+ location=to_entity_location(api_entity.location) if api_entity.location is not None else None,
+ entity_type=api_entity.entity_type,
+ entity_scores={} if scores is None else dict(scores),
+ )
+
+
+def to_deidentify_string_response(response):
+ entities = [to_detected_entity(entity) for entity in (response.entities or []) if entity is not None]
+ return DeidentifyStringResponse(
+ processed_text=response.processed_text,
+ entities=entities,
+ metrics=to_metrics(response.metrics) if response.metrics is not None else None,
+ )
+
+
+def to_reidentify_string_response(response):
+ return ReidentifyStringResponse(
+ processed_text=response.processed_text,
+ metrics=to_metrics(response.metrics) if response.metrics is not None else None,
+ )
+
+
+def to_check_guardrails_response(response):
+ return CheckGuardrailsResponse(
+ text=response.text,
+ validation=_enum_or_default(GuardrailsValidation, response.validation, GuardrailsValidation.UNKNOWN),
+ toxic=response.toxic,
+ denied_topic=response.denied_topic,
+ )
+
+
+def to_get_run_response(run_id, response, source_type_cls):
+ outputs = [to_file_output(output) for output in (response.output or []) if output is not None]
+ return GetRunResponse(
+ run_id=run_id,
+ status=_enum_or_default(DetectRunStatus, response.status, DetectRunStatus.UNKNOWN),
+ output_type=_enum_or_default(source_type_cls, response.output_type, None),
+ output=outputs,
+ metrics=to_metrics(response.metrics) if response.metrics is not None else None,
+ message=response.message,
+ )
+
+
+def submitted_deidentify_file_response(run_id):
+ return DeidentifyFileResponse(run_id=run_id, status=None, output_type=None, output=[], metrics=None, message=None)
+
+
+def to_deidentify_file_response(run_id, run):
+ return DeidentifyFileResponse(
+ run_id=run_id,
+ status=run.status,
+ output_type=run.output_type,
+ output=run.output,
+ metrics=run.metrics,
+ message=run.message,
+ )
+
+
+def to_reidentify_file_response(response, source_type_cls):
+ outputs = [to_file_output(output) for output in (response.output or []) if output is not None]
+ return ReidentifyFileResponse(
+ status=_enum_or_default(DetectRunStatus, response.status, DetectRunStatus.UNKNOWN),
+ output_type=_enum_or_default(source_type_cls, response.output_type, None),
+ output=outputs,
+ metrics=to_metrics(response.metrics) if response.metrics is not None else None,
+ )
diff --git a/common/vault/detect/_models.py b/common/vault/detect/_models.py
new file mode 100644
index 00000000..027ea64d
--- /dev/null
+++ b/common/vault/detect/_models.py
@@ -0,0 +1,315 @@
+from __future__ import annotations
+
+from typing import BinaryIO, Dict, List
+
+
+class Metrics:
+ def __init__(self, size: float = None, word_count: int = None,
+ character_count: int = None, slides: int = None,
+ pages: int = None, duration: float = None):
+ self.size = size
+ self.word_count = word_count
+ self.character_count = character_count
+ self.slides = slides
+ self.pages = pages
+ self.duration = duration
+
+
+class FileOutput:
+ def __init__(self, processed_file: str = None,
+ processed_file_type: str = None,
+ processed_file_extension: "FileDataFormat" = None):
+ self.processed_file = processed_file
+ self.processed_file_type = processed_file_type
+ self.processed_file_extension = processed_file_extension
+
+
+class RedactionRule:
+ def _api_entity_name(self):
+ return None
+
+ def _api_redaction_type(self):
+ return None
+
+ def _api_token_group_name(self):
+ return None
+
+ def _api_redaction_pattern(self):
+ return None
+
+
+class ShiftDates:
+ def __init__(self, min_days: int = None, max_days: int = None):
+ self.min_days = min_days
+ self.max_days = max_days
+
+
+class Transformation:
+ def __init__(self, shift_dates: ShiftDates = None):
+ self.shift_dates = shift_dates
+
+
+class Entity:
+ def __init__(self, entity_type: "EntityType" = None,
+ deidentification_type: "DeidentificationType" = None,
+ destination: str = None,
+ transformation: Transformation = None):
+ self.entity_type = entity_type
+ self.deidentification_type = deidentification_type
+ self.destination = destination
+ self.transformation = transformation
+
+
+class CustomType:
+ def __init__(self, label: str = None, match: List[str] = None):
+ self.label = label
+ self.match = match
+
+
+class ObjectEntity:
+ def __init__(self, entity_type: "ObjectEntityType" = None,
+ deidentification_type: "ObjectDeidentificationType" = None):
+ self.entity_type = entity_type
+ self.deidentification_type = deidentification_type
+
+
+class Detect:
+ def __init__(self, entities: List[Entity] = None,
+ object_entities: List[ObjectEntity] = None,
+ restrict: List[str] = None, skip: List[str] = None,
+ custom_types: List[CustomType] = None,
+ return_entities: "ReturnEntitiesType" = None):
+ self.entities = entities
+ self.object_entities = object_entities
+ self.restrict = restrict
+ self.skip = skip
+ self.custom_types = custom_types
+ self.return_entities = return_entities
+
+
+class FileMapping:
+ def __init__(self, source: str = None, destination: str = None,
+ output_file_name_suffix: str = None,
+ entities_destination: str = None,
+ object_entities_destination: str = None):
+ self.source = source
+ self.destination = destination
+ self.output_file_name_suffix = output_file_name_suffix
+ self.entities_destination = entities_destination
+ self.object_entities_destination = object_entities_destination
+
+
+class Bleep:
+ def __init__(self, start_padding: float = None, stop_padding: float = None,
+ frequency: int = None, gain: int = None):
+ self.start_padding = start_padding
+ self.stop_padding = stop_padding
+ self.frequency = frequency
+ self.gain = gain
+
+
+class Audio:
+ def __init__(self, output_processed_audio: bool = None,
+ output_transcription: "OutputTranscriptionType" = None,
+ bleep: Bleep = None):
+ self.output_processed_audio = output_processed_audio
+ self.output_transcription = output_transcription
+ self.bleep = bleep
+
+
+class Pdf:
+ def __init__(self, processing_mode: "PdfProcessingMode" = None,
+ density: int = None, max_resolution: int = None):
+ self.processing_mode = processing_mode
+ self.density = density
+ self.max_resolution = max_resolution
+
+
+class Document:
+ def __init__(self, pdf: Pdf = None):
+ self.pdf = pdf
+
+
+class Image:
+ def __init__(self, output_processed_image: bool = None,
+ output_ocr_text: bool = None,
+ masking_method: "MaskingMethod" = None):
+ self.output_processed_image = output_processed_image
+ self.output_ocr_text = output_ocr_text
+ self.masking_method = masking_method
+
+
+class Media:
+ def __init__(self, audio: Audio = None, document: Document = None,
+ image: Image = None):
+ self.audio = audio
+ self.document = document
+ self.image = image
+
+
+class DetectConfiguration:
+ def __init__(self, name: str = None, description: str = None,
+ detect: Detect = None,
+ file_mapping: List[FileMapping] = None,
+ media: Media = None):
+ self.name = name
+ self.description = description
+ self.detect = detect
+ self.file_mapping = file_mapping
+ self.media = media
+
+
+class PollOptions:
+ def __init__(self, wait_time: int = None, max_attempts: int = None):
+ self.wait_time = wait_time
+ self.max_attempts = max_attempts
+
+
+class EntityLocation:
+ def __init__(self, start_index: int = None, end_index: int = None,
+ start_index_processed: int = None,
+ end_index_processed: int = None):
+ self.start_index = start_index
+ self.end_index = end_index
+ self.start_index_processed = start_index_processed
+ self.end_index_processed = end_index_processed
+
+
+class DetectedEntity:
+ def __init__(self, token: str = None, value: str = None,
+ location: EntityLocation = None,
+ entity_type: str = None,
+ entity_scores: Dict[str, float] = None):
+ self.token = token
+ self.value = value
+ self.location = location
+ self.entity_type = entity_type
+ self.entity_scores = entity_scores
+
+
+class DeidentifyStringRequest:
+ def __init__(self, text: str,
+ configuration_id: str = None,
+ configuration: DetectConfiguration = None):
+ self.text = text
+ self.configuration_id = configuration_id
+ self.configuration = configuration
+
+
+class DeidentifyStringResponse:
+ def __init__(self, processed_text: str = None,
+ entities: List[DetectedEntity] = None,
+ metrics: Metrics = None):
+ self.processed_text = processed_text
+ self.entities = entities
+ self.metrics = metrics
+
+
+class DeidentifyFileRequest:
+ def __init__(self, data_source: "DeidentifySourceType" = None,
+ value: str = None,
+ data_format: "FileDataFormat" = None,
+ configuration_id: str = None,
+ configuration: DetectConfiguration = None,
+ file: BinaryIO = None, file_path: str = None,
+ poll_options: PollOptions = None,
+ output_directory: str = None):
+ self.data_source = data_source
+ self.value = value
+ self.data_format = data_format
+ self.configuration_id = configuration_id
+ self.configuration = configuration
+ self.file = file
+ self.file_path = file_path
+ self.poll_options = poll_options
+ self.output_directory = output_directory
+
+
+class DeidentifyFileResponse:
+ def __init__(self, run_id: str = None,
+ status: "DetectRunStatus" = None,
+ output_type: "DeidentifySourceType" = None,
+ output: List[FileOutput] = None,
+ metrics: Metrics = None,
+ message: str = None):
+ self.run_id = run_id
+ self.status = status
+ self.output_type = output_type
+ self.output = output
+ self.metrics = metrics
+ self.message = message
+
+
+class GetRunRequest:
+ def __init__(self, run_id: str):
+ self.run_id = run_id
+
+
+class GetRunResponse:
+ def __init__(self, run_id: str = None,
+ status: "DetectRunStatus" = None,
+ output_type: "DeidentifySourceType" = None,
+ output: List[FileOutput] = None,
+ metrics: Metrics = None,
+ message: str = None):
+ self.run_id = run_id
+ self.status = status
+ self.output_type = output_type
+ self.output = output
+ self.metrics = metrics
+ self.message = message
+
+
+class ReidentifyStringRequest:
+ def __init__(self, text: str,
+ redaction_level: List[RedactionRule] = None):
+ self.text = text
+ self.redaction_level = redaction_level
+
+
+class ReidentifyStringResponse:
+ def __init__(self, processed_text: str = None, metrics: Metrics = None):
+ self.processed_text = processed_text
+ self.metrics = metrics
+
+
+class ReidentifyFileRequest:
+ def __init__(self, data_source: "ReidentifySourceType" = None,
+ value: str = None,
+ data_format: "FileDataFormat" = None,
+ redaction_level: List[RedactionRule] = None):
+ self.data_source = data_source
+ self.value = value
+ self.data_format = data_format
+ self.redaction_level = redaction_level
+
+
+class ReidentifyFileResponse:
+ def __init__(self, status: "DetectRunStatus" = None,
+ output_type: "ReidentifySourceType" = None,
+ output: List[FileOutput] = None,
+ metrics: Metrics = None):
+ self.status = status
+ self.output_type = output_type
+ self.output = output
+ self.metrics = metrics
+
+
+class CheckGuardrailsRequest:
+ def __init__(self, text: str,
+ check_toxicity: bool = None,
+ deny_topics: List[str] = None):
+ self.text = text
+ self.check_toxicity = check_toxicity
+ self.deny_topics = deny_topics
+
+
+class CheckGuardrailsResponse:
+ def __init__(self, text: str = None,
+ validation: "GuardrailsValidation" = None,
+ toxic: bool = None,
+ denied_topic: bool = None):
+ self.text = text
+ self.validation = validation
+ self.toxic = toxic
+ self.denied_topic = denied_topic
diff --git a/common/vault/detect/_polling.py b/common/vault/detect/_polling.py
new file mode 100644
index 00000000..f9805fd6
--- /dev/null
+++ b/common/vault/detect/_polling.py
@@ -0,0 +1,56 @@
+import time
+
+from common.utils import SkyflowMessages
+from common.utils.logger import log_info
+from common.utils.enums.detect import DetectRunStatus
+
+from ._constants import (
+ DEFAULT_WAIT_TIME_SECONDS,
+ DEFAULT_MAX_ATTEMPTS,
+ INITIAL_DELAY_SECONDS,
+ MAX_DELAY_SECONDS,
+ DELAY_MULTIPLIER,
+)
+from ._models import GetRunResponse
+
+_TERMINAL_STATUSES = (DetectRunStatus.SUCCESS, DetectRunStatus.FAILED, DetectRunStatus.UNKNOWN)
+
+
+def _effective_wait_time(poll_options):
+ return DEFAULT_WAIT_TIME_SECONDS if poll_options.wait_time is None else poll_options.wait_time
+
+
+def _effective_max_attempts(poll_options):
+ return DEFAULT_MAX_ATTEMPTS if poll_options.max_attempts is None else poll_options.max_attempts
+
+
+def poll_run(run_id, poll_options, fetcher, logger=None, sleeper=time.sleep):
+ wait_time = _effective_wait_time(poll_options)
+ max_attempts = _effective_max_attempts(poll_options)
+ log_info(SkyflowMessages.Info.POLL_RUN_STARTED.value.format(run_id, wait_time, max_attempts), logger)
+
+ elapsed_seconds = 0
+ delay_seconds = INITIAL_DELAY_SECONDS
+ attempts = 0
+ while True:
+ run = fetcher(run_id)
+ attempts += 1
+ if run is None or run.status is None:
+ run = GetRunResponse(
+ run_id=run_id,
+ status=DetectRunStatus.UNKNOWN,
+ output_type=None,
+ output=[],
+ metrics=None,
+ message=None,
+ )
+ if run.status in _TERMINAL_STATUSES:
+ log_info(SkyflowMessages.Info.POLL_RUN_TERMINAL.value, logger)
+ return run
+ if attempts >= max_attempts or elapsed_seconds >= wait_time:
+ log_info(SkyflowMessages.Info.POLL_RUN_BUDGET_EXHAUSTED.value, logger)
+ return run
+ sleep_seconds = min(delay_seconds, wait_time - elapsed_seconds)
+ sleeper(sleep_seconds)
+ elapsed_seconds += sleep_seconds
+ delay_seconds = min(delay_seconds * DELAY_MULTIPLIER, MAX_DELAY_SECONDS)
diff --git a/common/vault/detect/_validations.py b/common/vault/detect/_validations.py
new file mode 100644
index 00000000..0091db3e
--- /dev/null
+++ b/common/vault/detect/_validations.py
@@ -0,0 +1,88 @@
+import os
+
+from common.errors import SkyflowError
+from common.utils import SkyflowMessages
+
+from ._constants import (
+ MIN_WAIT_TIME_SECONDS,
+ MAX_WAIT_TIME_SECONDS,
+ MIN_MAX_ATTEMPTS,
+ MAX_MAX_ATTEMPTS,
+)
+
+_INVALID_INPUT = SkyflowMessages.ErrorCodes.INVALID_INPUT.value
+
+
+def _is_blank(value):
+ return value is None or not str(value).strip()
+
+
+def _invalid(message):
+ return SkyflowError(message, _INVALID_INPUT)
+
+
+def validate_deidentify_string_request(request):
+ if request is None:
+ raise _invalid(SkyflowMessages.Error.DEIDENTIFY_STRING_REQUEST_NULL.value)
+ if _is_blank(request.text):
+ raise _invalid(SkyflowMessages.Error.INVALID_TEXT_IN_DEIDENTIFY_STRING.value)
+
+
+def validate_deidentify_file_request(request):
+ if request is None:
+ raise _invalid(SkyflowMessages.Error.DEIDENTIFY_FILE_REQUEST_NULL.value)
+ has_local_file = request.file is not None or request.file_path is not None
+ if has_local_file:
+ if not _is_blank(request.value):
+ raise _invalid(SkyflowMessages.Error.MULTIPLE_FILE_SOURCES_IN_DEIDENTIFY_FILE.value)
+ if request.file_path is not None and not os.path.isfile(request.file_path):
+ raise _invalid(SkyflowMessages.Error.FILE_NOT_FOUND_TO_DEIDENTIFY.value)
+ else:
+ if request.data_source is None:
+ raise _invalid(SkyflowMessages.Error.INVALID_DATA_SOURCE_IN_DEIDENTIFY_FILE.value)
+ if _is_blank(request.value):
+ raise _invalid(SkyflowMessages.Error.INVALID_VALUE_IN_DEIDENTIFY_FILE.value)
+ validate_poll_options(request.poll_options)
+ if request.poll_options is None and not _is_blank(request.output_directory):
+ raise _invalid(SkyflowMessages.Error.OUTPUT_DIRECTORY_WITHOUT_POLL_OPTIONS.value)
+
+
+def validate_poll_options(poll_options):
+ if poll_options is None:
+ return
+ wait_time = poll_options.wait_time
+ if wait_time is not None and (wait_time < MIN_WAIT_TIME_SECONDS or wait_time > MAX_WAIT_TIME_SECONDS):
+ raise _invalid(SkyflowMessages.Error.INVALID_WAIT_TIME_IN_POLL_OPTIONS.value)
+ max_attempts = poll_options.max_attempts
+ if max_attempts is not None and (max_attempts < MIN_MAX_ATTEMPTS or max_attempts > MAX_MAX_ATTEMPTS):
+ raise _invalid(SkyflowMessages.Error.INVALID_MAX_ATTEMPTS_IN_POLL_OPTIONS.value)
+
+
+def validate_reidentify_string_request(request):
+ if request is None:
+ raise _invalid(SkyflowMessages.Error.REIDENTIFY_STRING_REQUEST_NULL.value)
+ if _is_blank(request.text):
+ raise _invalid(SkyflowMessages.Error.INVALID_TEXT_IN_REIDENTIFY_STRING.value)
+
+
+def validate_get_run_request(request):
+ if request is None:
+ raise _invalid(SkyflowMessages.Error.GET_RUN_REQUEST_NULL.value)
+ if _is_blank(request.run_id):
+ raise _invalid(SkyflowMessages.Error.INVALID_RUN_ID_IN_GET_RUN.value)
+
+
+def validate_check_guardrails_request(request):
+ if request is None:
+ raise _invalid(SkyflowMessages.Error.CHECK_GUARDRAILS_REQUEST_NULL.value)
+ if _is_blank(request.text):
+ raise _invalid(SkyflowMessages.Error.INVALID_TEXT_IN_CHECK_GUARDRAILS.value)
+
+
+def validate_reidentify_file_request(request):
+ if request is None:
+ raise _invalid(SkyflowMessages.Error.REIDENTIFY_FILE_REQUEST_NULL.value)
+ if request.data_source is None:
+ raise _invalid(SkyflowMessages.Error.INVALID_DATA_SOURCE_IN_REIDENTIFY_FILE.value)
+ if _is_blank(request.value):
+ raise _invalid(SkyflowMessages.Error.INVALID_VALUE_IN_REIDENTIFY_FILE.value)
diff --git a/flowvault/README.md b/flowvault/README.md
index f2b2a2c2..182ada88 100644
--- a/flowvault/README.md
+++ b/flowvault/README.md
@@ -43,6 +43,13 @@ The `flowvault` module is a Skyflow Python SDK for vault operations. It shares i
- [Upload Files](#upload-files)
- [Delete Files](#delete-files)
- [Custom Request Headers](#custom-request-headers)
+- [DetectController — Detect V2](#detectcontroller--detect-v2)
+ - [deidentify_string](#deidentify_string)
+ - [deidentify_file](#deidentify_file)
+ - [get_run](#get_run)
+ - [reidentify_string](#reidentify_string)
+ - [reidentify_file](#reidentify_file)
+ - [check_guardrails](#check_guardrails)
- [Error Handling](#error-handling)
- [Two layers of errors](#two-layers-of-errors)
- [Per-record success and failure](#per-record-success-and-failure)
@@ -972,6 +979,179 @@ The same pattern applies to every operation, via its corresponding options class
| `upload_files` | `UploadFilesOptions` |
| `delete_files` | `DeleteFilesOptions` |
+# Detect
+
+Detect V2 detects and de-identifies sensitive data in strings and files, re-identifies tokens, and screens text against guardrails. Get the controller with `skyflow_client.detect()` (or `skyflow_client.detect('')` to select one of several configured vaults). The `vault_id` is filled in from the vault config for every method.
+
+Detect configurations are created in Studio or through the REST API — the SDK does not create or manage them. Import request/response models from `skyflow.vault.detect` and enums from `skyflow.utils.enums`.
+
+```python
+detect = skyflow_client.detect()
+```
+
+## deidentify_string
+
+Synchronous. Detects and de-identifies sensitive data in a string. Pass exactly one configuration source: a stored `configuration_id`, or an inline `configuration`.
+
+```python
+from skyflow.vault.detect import DeidentifyStringRequest
+
+response = skyflow_client.detect().deidentify_string(
+ DeidentifyStringRequest(
+ text='My name is John Doe, and my email is johndoe@acme.com.',
+ configuration_id='',
+ )
+)
+
+print(response.processed_text)
+for entity in response.entities:
+ print(entity.entity_type, entity.token, entity.location.start_index, entity.entity_scores)
+```
+
+An inline configuration is built from `DetectConfiguration` / `Detect` / `Entity`:
+
+```python
+from skyflow.vault.detect import DeidentifyStringRequest, DetectConfiguration, Detect, Entity
+from skyflow.utils.enums import EntityType, DeidentificationType
+
+response = skyflow_client.detect().deidentify_string(
+ DeidentifyStringRequest(
+ text='My name is John Doe.',
+ configuration=DetectConfiguration(
+ detect=Detect(entities=[
+ Entity(entity_type=EntityType.NAME, deidentification_type=DeidentificationType.VAULT_TOKEN, destination='persons.name'),
+ ]),
+ ),
+ )
+)
+```
+
+Returns a `DeidentifyStringResponse` with `processed_text`, `entities` (each a `DetectedEntity` with `token`, `value`, `location`, `entity_type`, `entity_scores`), and `metrics`.
+
+## deidentify_file
+
+De-identifies a file. The API is asynchronous. By default the SDK submits the run and returns a `DeidentifyFileResponse` with `run_id` set and `status` as `None` — retrieve the result later with `get_run`. Supply exactly one of `value` (with `data_source`), `file`, or `file_path`; a local `file`/`file_path` is read, base64-encoded, and its format inferred from the extension.
+
+```python
+from skyflow.vault.detect import DeidentifyFileRequest
+
+response = skyflow_client.detect().deidentify_file(
+ DeidentifyFileRequest(file_path='/data/intake/patient-notes.pdf', configuration_id='')
+)
+print(response.run_id) # status is None; nothing written to disk
+```
+
+Pass `poll_options` to submit and poll with exponential backoff (1, 2, 4, 8, 16, then 32 seconds), bounded by `wait_time` (default 60, max 300 seconds) and `max_attempts` (default and max 23). On `SUCCESS`, outputs for a local `file`/`file_path` request are written to `output_directory` (only valid with `poll_options`).
+
+```python
+from skyflow.vault.detect import DeidentifyFileRequest, PollOptions
+from skyflow.utils.enums import DetectRunStatus
+
+response = skyflow_client.detect().deidentify_file(
+ DeidentifyFileRequest(
+ file_path='/data/intake/patient-notes.pdf',
+ configuration_id='',
+ poll_options=PollOptions(wait_time=64),
+ output_directory='/data/out',
+ )
+)
+
+if response.status == DetectRunStatus.SUCCESS:
+ print(response.metrics.pages) # /data/out/processed-patient-notes.pdf written
+elif response.status in (DetectRunStatus.IN_PROGRESS, DetectRunStatus.QUEUED):
+ pass # budget ran out — poll later with get_run(run_id)
+```
+
+A file at a presigned URL is referenced through `data_source` + `value` (no local-file auto-write applies in that case):
+
+```python
+from skyflow.vault.detect import DeidentifyFileRequest
+from skyflow.utils.enums import DeidentifySourceType, FileDataFormat
+
+skyflow_client.detect().deidentify_file(
+ DeidentifyFileRequest(
+ data_source=DeidentifySourceType.PRESIGNED_URL,
+ value='',
+ data_format=FileDataFormat.PDF,
+ configuration_id='',
+ )
+)
+```
+
+## get_run
+
+Retrieves the status and, once complete, the outputs of a Detect file run.
+
+```python
+from skyflow.vault.detect import GetRunRequest
+from skyflow.utils.enums import DetectRunStatus
+
+run = skyflow_client.detect().get_run(GetRunRequest(run_id=''))
+if run.status == DetectRunStatus.SUCCESS:
+ for output in run.output:
+ print(output.processed_file_type, output.processed_file_extension)
+```
+
+## reidentify_string
+
+Synchronous. Replaces tokens in a string with their original values or a redacted rendering. Each `RedactionLevel` targets a token group (`token_group_name`, flowvault) or entity (`entity_name`, skyvault) and sets a replacement (`redaction_pattern` or `redaction_type`); vault-specific validation is performed server-side.
+
+```python
+from skyflow.vault.detect import ReidentifyStringRequest, RedactionLevel
+
+response = skyflow_client.detect().reidentify_string(
+ ReidentifyStringRequest(
+ text='My name is [NAME_1].',
+ redaction_level=[RedactionLevel(token_group_name='personTokenGroup', redaction_pattern='personMaskPattern')],
+ )
+)
+print(response.processed_text)
+```
+
+## reidentify_file
+
+Synchronous — the re-identified file is returned in the response. Supply the file through `data_source` + `value` (base64 or presigned URL); decode and write any output files yourself.
+
+```python
+import base64
+from skyflow.vault.detect import ReidentifyFileRequest, RedactionLevel
+from skyflow.utils.enums import ReidentifySourceType, FileDataFormat, DetectRunStatus
+
+with open('/data/redacted/notes.txt', 'rb') as handle:
+ encoded = base64.b64encode(handle.read()).decode('utf-8')
+
+response = skyflow_client.detect().reidentify_file(
+ ReidentifyFileRequest(
+ data_source=ReidentifySourceType.BASE64,
+ value=encoded,
+ data_format=FileDataFormat.TXT,
+ redaction_level=[RedactionLevel(token_group_name='', redaction_pattern='')],
+ )
+)
+
+if response.status == DetectRunStatus.SUCCESS:
+ for index, output in enumerate(response.output):
+ with open(f'reidentified-{index}', 'wb') as out:
+ out.write(base64.b64decode(output.processed_file))
+```
+
+## check_guardrails
+
+Synchronous. Screens text for toxicity and denied topics.
+
+```python
+from skyflow.vault.detect import CheckGuardrailsRequest
+from skyflow.utils.enums import GuardrailsValidation
+
+response = skyflow_client.detect().check_guardrails(
+ CheckGuardrailsRequest(text='', check_toxicity=True, deny_topics=['politics', 'medical advice'])
+)
+if response.validation == GuardrailsValidation.FAILED:
+ print('blocked', response.toxic, response.denied_topic)
+```
+
+Every method raises `skyflow.error.SkyflowError` on validation failure, credential failure, or an API error — see [Error Handling](#error-handling).
+
# Error Handling
## Two layers of errors
diff --git a/flowvault/api-report/skyflow.api.json b/flowvault/api-report/skyflow.api.json
index ecee35b4..97504b28 100644
--- a/flowvault/api-report/skyflow.api.json
+++ b/flowvault/api-report/skyflow.api.json
@@ -29,15 +29,167 @@
"skyflow.utils.enums.CustomHeaderKey.REQUEST_ID_HEADER": "attr = 'x-request-id'",
"skyflow.utils.enums.CustomHeaderKey.SKYFLOW_ACCOUNT_ID": "attr = 'x-skyflow-account-id'",
"skyflow.utils.enums.CustomHeaderKey.SKYFLOW_ACCOUNT_NAME": "attr = 'x-skyflow-account-name'",
+ "skyflow.utils.enums.DeidentificationType": "class (Enum)",
+ "skyflow.utils.enums.DeidentificationType.ENTITY_ONLY": "attr = 'ENTITY_ONLY'",
+ "skyflow.utils.enums.DeidentificationType.ENTITY_UNIQUE_COUNTER": "attr = 'ENTITY_UNIQUE_COUNTER'",
+ "skyflow.utils.enums.DeidentificationType.MASK": "attr = 'MASK'",
+ "skyflow.utils.enums.DeidentificationType.UNKNOWN": "attr = 'UNKNOWN'",
+ "skyflow.utils.enums.DeidentificationType.VAULT_TOKEN": "attr = 'VAULT_TOKEN'",
+ "skyflow.utils.enums.DeidentifySourceType": "class (Enum)",
+ "skyflow.utils.enums.DeidentifySourceType.BASE64": "attr = 'BASE64'",
+ "skyflow.utils.enums.DeidentifySourceType.PRESIGNED_URL": "attr = 'PRESIGNED_URL'",
+ "skyflow.utils.enums.DetectRunStatus": "class (Enum)",
+ "skyflow.utils.enums.DetectRunStatus.FAILED": "attr = 'FAILED'",
+ "skyflow.utils.enums.DetectRunStatus.IN_PROGRESS": "attr = 'IN_PROGRESS'",
+ "skyflow.utils.enums.DetectRunStatus.QUEUED": "attr = 'QUEUED'",
+ "skyflow.utils.enums.DetectRunStatus.SUCCESS": "attr = 'SUCCESS'",
+ "skyflow.utils.enums.DetectRunStatus.UNKNOWN": "attr = 'UNKNOWN'",
+ "skyflow.utils.enums.EntityType": "class (Enum)",
+ "skyflow.utils.enums.EntityType.ACCOUNT_NUMBER": "attr = 'ACCOUNT_NUMBER'",
+ "skyflow.utils.enums.EntityType.AGE": "attr = 'AGE'",
+ "skyflow.utils.enums.EntityType.ALL": "attr = 'ALL'",
+ "skyflow.utils.enums.EntityType.BANK_ACCOUNT": "attr = 'BANK_ACCOUNT'",
+ "skyflow.utils.enums.EntityType.BLOOD_TYPE": "attr = 'BLOOD_TYPE'",
+ "skyflow.utils.enums.EntityType.CONDITION": "attr = 'CONDITION'",
+ "skyflow.utils.enums.EntityType.CORPORATE_ACTION": "attr = 'CORPORATE_ACTION'",
+ "skyflow.utils.enums.EntityType.CREDIT_CARD": "attr = 'CREDIT_CARD'",
+ "skyflow.utils.enums.EntityType.CREDIT_CARD_EXPIRATION": "attr = 'CREDIT_CARD_EXPIRATION'",
+ "skyflow.utils.enums.EntityType.CVV": "attr = 'CVV'",
+ "skyflow.utils.enums.EntityType.DATE": "attr = 'DATE'",
+ "skyflow.utils.enums.EntityType.DATE_INTERVAL": "attr = 'DATE_INTERVAL'",
+ "skyflow.utils.enums.EntityType.DAY": "attr = 'DAY'",
+ "skyflow.utils.enums.EntityType.DOB": "attr = 'DOB'",
+ "skyflow.utils.enums.EntityType.DOSE": "attr = 'DOSE'",
+ "skyflow.utils.enums.EntityType.DRIVER_LICENSE": "attr = 'DRIVER_LICENSE'",
+ "skyflow.utils.enums.EntityType.DRUG": "attr = 'DRUG'",
+ "skyflow.utils.enums.EntityType.DURATION": "attr = 'DURATION'",
+ "skyflow.utils.enums.EntityType.EFFECT": "attr = 'EFFECT'",
+ "skyflow.utils.enums.EntityType.EMAIL_ADDRESS": "attr = 'EMAIL_ADDRESS'",
+ "skyflow.utils.enums.EntityType.EVENT": "attr = 'EVENT'",
+ "skyflow.utils.enums.EntityType.FILENAME": "attr = 'FILENAME'",
+ "skyflow.utils.enums.EntityType.FINANCIAL_METRIC": "attr = 'FINANCIAL_METRIC'",
+ "skyflow.utils.enums.EntityType.GENDER": "attr = 'GENDER'",
+ "skyflow.utils.enums.EntityType.HEALTHCARE_NUMBER": "attr = 'HEALTHCARE_NUMBER'",
+ "skyflow.utils.enums.EntityType.INJURY": "attr = 'INJURY'",
+ "skyflow.utils.enums.EntityType.IP_ADDRESS": "attr = 'IP_ADDRESS'",
+ "skyflow.utils.enums.EntityType.LANGUAGE": "attr = 'LANGUAGE'",
+ "skyflow.utils.enums.EntityType.LOCATION": "attr = 'LOCATION'",
+ "skyflow.utils.enums.EntityType.LOCATION_ADDRESS": "attr = 'LOCATION_ADDRESS'",
+ "skyflow.utils.enums.EntityType.LOCATION_ADDRESS_STREET": "attr = 'LOCATION_ADDRESS_STREET'",
+ "skyflow.utils.enums.EntityType.LOCATION_CITY": "attr = 'LOCATION_CITY'",
+ "skyflow.utils.enums.EntityType.LOCATION_COORDINATE": "attr = 'LOCATION_COORDINATE'",
+ "skyflow.utils.enums.EntityType.LOCATION_COUNTRY": "attr = 'LOCATION_COUNTRY'",
+ "skyflow.utils.enums.EntityType.LOCATION_STATE": "attr = 'LOCATION_STATE'",
+ "skyflow.utils.enums.EntityType.LOCATION_ZIP": "attr = 'LOCATION_ZIP'",
+ "skyflow.utils.enums.EntityType.MARITAL_STATUS": "attr = 'MARITAL_STATUS'",
+ "skyflow.utils.enums.EntityType.MEDICAL_CODE": "attr = 'MEDICAL_CODE'",
+ "skyflow.utils.enums.EntityType.MEDICAL_PROCESS": "attr = 'MEDICAL_PROCESS'",
+ "skyflow.utils.enums.EntityType.MONEY": "attr = 'MONEY'",
+ "skyflow.utils.enums.EntityType.MONTH": "attr = 'MONTH'",
+ "skyflow.utils.enums.EntityType.NAME": "attr = 'NAME'",
+ "skyflow.utils.enums.EntityType.NAME_FAMILY": "attr = 'NAME_FAMILY'",
+ "skyflow.utils.enums.EntityType.NAME_GIVEN": "attr = 'NAME_GIVEN'",
+ "skyflow.utils.enums.EntityType.NAME_MEDICAL_PROFESSIONAL": "attr = 'NAME_MEDICAL_PROFESSIONAL'",
+ "skyflow.utils.enums.EntityType.NONE": "attr = 'NONE'",
+ "skyflow.utils.enums.EntityType.NUMERICAL_PII": "attr = 'NUMERICAL_PII'",
+ "skyflow.utils.enums.EntityType.OCCUPATION": "attr = 'OCCUPATION'",
+ "skyflow.utils.enums.EntityType.ORGANIZATION": "attr = 'ORGANIZATION'",
+ "skyflow.utils.enums.EntityType.ORGANIZATION_ID": "attr = 'ORGANIZATION_ID'",
+ "skyflow.utils.enums.EntityType.ORGANIZATION_MEDICAL_FACILITY": "attr = 'ORGANIZATION_MEDICAL_FACILITY'",
+ "skyflow.utils.enums.EntityType.ORIGIN": "attr = 'ORIGIN'",
+ "skyflow.utils.enums.EntityType.PASSPORT_NUMBER": "attr = 'PASSPORT_NUMBER'",
+ "skyflow.utils.enums.EntityType.PASSWORD": "attr = 'PASSWORD'",
+ "skyflow.utils.enums.EntityType.PHONE_NUMBER": "attr = 'PHONE_NUMBER'",
+ "skyflow.utils.enums.EntityType.PHYSICAL_ATTRIBUTE": "attr = 'PHYSICAL_ATTRIBUTE'",
+ "skyflow.utils.enums.EntityType.POLITICAL_AFFILIATION": "attr = 'POLITICAL_AFFILIATION'",
+ "skyflow.utils.enums.EntityType.PRODUCT": "attr = 'PRODUCT'",
+ "skyflow.utils.enums.EntityType.PROJECT": "attr = 'PROJECT'",
+ "skyflow.utils.enums.EntityType.RELIGION": "attr = 'RELIGION'",
+ "skyflow.utils.enums.EntityType.ROUTING_NUMBER": "attr = 'ROUTING_NUMBER'",
+ "skyflow.utils.enums.EntityType.SEXUALITY": "attr = 'SEXUALITY'",
+ "skyflow.utils.enums.EntityType.SSN": "attr = 'SSN'",
+ "skyflow.utils.enums.EntityType.STATISTICS": "attr = 'STATISTICS'",
+ "skyflow.utils.enums.EntityType.TIME": "attr = 'TIME'",
+ "skyflow.utils.enums.EntityType.TREND": "attr = 'TREND'",
+ "skyflow.utils.enums.EntityType.URL": "attr = 'URL'",
+ "skyflow.utils.enums.EntityType.USERNAME": "attr = 'USERNAME'",
+ "skyflow.utils.enums.EntityType.VEHICLE_ID": "attr = 'VEHICLE_ID'",
+ "skyflow.utils.enums.EntityType.YEAR": "attr = 'YEAR'",
+ "skyflow.utils.enums.EntityType.ZODIAC_SIGN": "attr = 'ZODIAC_SIGN'",
"skyflow.utils.enums.EnvUrls": "class (Enum)",
"skyflow.utils.enums.EnvUrls.DEV": "attr = 'skyvault.skyflowapis.dev'",
"skyflow.utils.enums.EnvUrls.PROD": "attr = 'skyvault.skyflowapis.com'",
"skyflow.utils.enums.EnvUrls.SANDBOX": "attr = 'skyvault.skyflowapis-preview.com'",
"skyflow.utils.enums.EnvUrls.STAGE": "attr = 'skyvault.skyflowapis.tech'",
+ "skyflow.utils.enums.FileDataFormat": "class (Enum)",
+ "skyflow.utils.enums.FileDataFormat.BMP": "attr = 'bmp'",
+ "skyflow.utils.enums.FileDataFormat.CSV": "attr = 'csv'",
+ "skyflow.utils.enums.FileDataFormat.DCM": "attr = 'dcm'",
+ "skyflow.utils.enums.FileDataFormat.DOC": "attr = 'doc'",
+ "skyflow.utils.enums.FileDataFormat.DOCX": "attr = 'docx'",
+ "skyflow.utils.enums.FileDataFormat.GIF": "attr = 'gif'",
+ "skyflow.utils.enums.FileDataFormat.JPEG": "attr = 'jpeg'",
+ "skyflow.utils.enums.FileDataFormat.JPG": "attr = 'jpg'",
+ "skyflow.utils.enums.FileDataFormat.JSON": "attr = 'json'",
+ "skyflow.utils.enums.FileDataFormat.JSONL": "attr = 'jsonl'",
+ "skyflow.utils.enums.FileDataFormat.MP3": "attr = 'mp3'",
+ "skyflow.utils.enums.FileDataFormat.PDF": "attr = 'pdf'",
+ "skyflow.utils.enums.FileDataFormat.PNG": "attr = 'png'",
+ "skyflow.utils.enums.FileDataFormat.PPT": "attr = 'ppt'",
+ "skyflow.utils.enums.FileDataFormat.PPTX": "attr = 'pptx'",
+ "skyflow.utils.enums.FileDataFormat.TIF": "attr = 'tif'",
+ "skyflow.utils.enums.FileDataFormat.TIFF": "attr = 'tiff'",
+ "skyflow.utils.enums.FileDataFormat.TXT": "attr = 'txt'",
+ "skyflow.utils.enums.FileDataFormat.WAV": "attr = 'wav'",
+ "skyflow.utils.enums.FileDataFormat.XLS": "attr = 'xls'",
+ "skyflow.utils.enums.FileDataFormat.XLSX": "attr = 'xlsx'",
+ "skyflow.utils.enums.FileDataFormat.XML": "attr = 'xml'",
+ "skyflow.utils.enums.FileDataFormat.ZIP": "attr = 'zip'",
"skyflow.utils.enums.FileUploadStatus": "class (Enum)",
"skyflow.utils.enums.FileUploadStatus.FAILED": "attr = 'FAILED'",
"skyflow.utils.enums.FileUploadStatus.SKIPPED": "attr = 'SKIPPED'",
"skyflow.utils.enums.FileUploadStatus.UPLOADED": "attr = 'UPLOADED'",
+ "skyflow.utils.enums.GuardrailsValidation": "class (Enum)",
+ "skyflow.utils.enums.GuardrailsValidation.FAILED": "attr = 'FAILED'",
+ "skyflow.utils.enums.GuardrailsValidation.PASSED": "attr = 'PASSED'",
+ "skyflow.utils.enums.GuardrailsValidation.UNKNOWN": "attr = 'UNKNOWN'",
+ "skyflow.utils.enums.MaskingMethod": "class (Enum)",
+ "skyflow.utils.enums.MaskingMethod.BLACKBOX": "attr = 'BLACKBOX'",
+ "skyflow.utils.enums.MaskingMethod.BLUR": "attr = 'BLUR'",
+ "skyflow.utils.enums.MaskingMethod.NONE": "attr = 'NONE'",
+ "skyflow.utils.enums.ObjectDeidentificationType": "class (Enum)",
+ "skyflow.utils.enums.ObjectDeidentificationType.REDACT": "attr = 'REDACT'",
+ "skyflow.utils.enums.ObjectDeidentificationType.UNKNOWN": "attr = 'UNKNOWN'",
+ "skyflow.utils.enums.ObjectDeidentificationType.UNREDACT": "attr = 'UNREDACT'",
+ "skyflow.utils.enums.ObjectEntityType": "class (Enum)",
+ "skyflow.utils.enums.ObjectEntityType.ALL": "attr = 'ALL'",
+ "skyflow.utils.enums.ObjectEntityType.FACE": "attr = 'FACE'",
+ "skyflow.utils.enums.ObjectEntityType.LICENSE_PLATE": "attr = 'LICENSE_PLATE'",
+ "skyflow.utils.enums.ObjectEntityType.LOGO": "attr = 'LOGO'",
+ "skyflow.utils.enums.ObjectEntityType.NONE": "attr = 'NONE'",
+ "skyflow.utils.enums.ObjectEntityType.SIGNATURE": "attr = 'SIGNATURE'",
+ "skyflow.utils.enums.OutputTranscriptionType": "class (Enum)",
+ "skyflow.utils.enums.OutputTranscriptionType.DIARIZED_TRANSCRIPTION": "attr = 'DIARIZED_TRANSCRIPTION'",
+ "skyflow.utils.enums.OutputTranscriptionType.MEDICAL_DIARIZED_TRANSCRIPTION": "attr = 'MEDICAL_DIARIZED_TRANSCRIPTION'",
+ "skyflow.utils.enums.OutputTranscriptionType.MEDICAL_TRANSCRIPTION": "attr = 'MEDICAL_TRANSCRIPTION'",
+ "skyflow.utils.enums.OutputTranscriptionType.NONE": "attr = 'NONE'",
+ "skyflow.utils.enums.OutputTranscriptionType.TRANSCRIPTION": "attr = 'TRANSCRIPTION'",
+ "skyflow.utils.enums.PdfProcessingMode": "class (Enum)",
+ "skyflow.utils.enums.PdfProcessingMode.NONE": "attr = 'NONE'",
+ "skyflow.utils.enums.PdfProcessingMode.OCR": "attr = 'OCR'",
+ "skyflow.utils.enums.PdfProcessingMode.TEXT_LAYER": "attr = 'TEXT_LAYER'",
+ "skyflow.utils.enums.RedactionType": "class (Enum)",
+ "skyflow.utils.enums.RedactionType.DEFAULT": "attr = 'DEFAULT'",
+ "skyflow.utils.enums.RedactionType.MASKED": "attr = 'MASKED'",
+ "skyflow.utils.enums.RedactionType.PLAIN_TEXT": "attr = 'PLAIN_TEXT'",
+ "skyflow.utils.enums.RedactionType.REDACTED": "attr = 'REDACTED'",
+ "skyflow.utils.enums.ReidentifySourceType": "class (Enum)",
+ "skyflow.utils.enums.ReidentifySourceType.BASE64": "attr = 'BASE64'",
+ "skyflow.utils.enums.ReidentifySourceType.PRESIGNED_URL": "attr = 'PRESIGNED_URL'",
+ "skyflow.utils.enums.ReturnEntitiesType": "class (Enum)",
+ "skyflow.utils.enums.ReturnEntitiesType.ALL": "attr = 'ALL'",
+ "skyflow.utils.enums.ReturnEntitiesType.EXCLUDE_SENSITIVE_DATA": "attr = 'EXCLUDE_SENSITIVE_DATA'",
+ "skyflow.utils.enums.ReturnEntitiesType.NONE": "attr = 'NONE'",
"skyflow.utils.enums.UpsertType": "class (Enum)",
"skyflow.utils.enums.UpsertType.REPLACE": "attr = 'REPLACE'",
"skyflow.utils.enums.UpsertType.UPDATE": "attr = 'UPDATE'",
diff --git a/flowvault/samples/README.md b/flowvault/samples/README.md
index a4e1b0dd..9aa6dcb6 100644
--- a/flowvault/samples/README.md
+++ b/flowvault/samples/README.md
@@ -44,6 +44,17 @@ python flowvault/samples/vault_api/insert_records.py
| [upload_files.py](vault_api/upload_files.py) | Upload files to file columns (`file_path` / `base64` / `file_object`) |
| [delete_files.py](vault_api/delete_files.py) | Delete files from file columns (by `skyflow_id` or `unique_values`) |
+## Detect V2
+
+| Sample | Demonstrates |
+|---|---|
+| [deidentify_string.py](detect_api/deidentify_string.py) | De-identify sensitive data in a string |
+| [deidentify_file.py](detect_api/deidentify_file.py) | De-identify a file; submit-only and submit-and-poll with `PollOptions` |
+| [get_run.py](detect_api/get_run.py) | Retrieve the status and outputs of a detect file run |
+| [reidentify_string.py](detect_api/reidentify_string.py) | Re-identify tokens in a string |
+| [reidentify_file.py](detect_api/reidentify_file.py) | Re-identify tokens in a file (synchronous) |
+| [check_guardrails.py](detect_api/check_guardrails.py) | Screen text for toxicity and denied topics |
+
## Custom headers & HTTP config
| Sample | Demonstrates |
diff --git a/flowvault/samples/detect_api/check_guardrails.py b/flowvault/samples/detect_api/check_guardrails.py
new file mode 100644
index 00000000..3af98586
--- /dev/null
+++ b/flowvault/samples/detect_api/check_guardrails.py
@@ -0,0 +1,44 @@
+from skyflow.error import SkyflowError
+from skyflow import Env, Skyflow, LogLevel
+from skyflow.vault.detect import CheckGuardrailsRequest
+from skyflow.utils.enums import GuardrailsValidation
+
+
+def perform_check_guardrails():
+ try:
+ vault_config = {
+ 'vault_id': '',
+ 'cluster_id': '',
+ 'env': Env.PROD,
+ 'credentials': {'path': ''},
+ }
+
+ skyflow_client = (
+ Skyflow.builder()
+ .add_vault_config(vault_config)
+ .set_log_level(LogLevel.ERROR)
+ .build()
+ )
+
+ request = CheckGuardrailsRequest(
+ text='',
+ check_toxicity=True,
+ deny_topics=['politics', 'medical advice'],
+ )
+
+ response = skyflow_client.detect().check_guardrails(request)
+
+ print(response.validation, response.toxic, response.denied_topic)
+ if response.validation == GuardrailsValidation.FAILED:
+ print('blocked')
+
+ except SkyflowError as error:
+ print('Skyflow Specific Error: ', {
+ 'code': error.http_code,
+ 'message': error.message,
+ 'details': error.details,
+ })
+
+
+if __name__ == '__main__':
+ perform_check_guardrails()
diff --git a/flowvault/samples/detect_api/deidentify_file.py b/flowvault/samples/detect_api/deidentify_file.py
new file mode 100644
index 00000000..92fbd821
--- /dev/null
+++ b/flowvault/samples/detect_api/deidentify_file.py
@@ -0,0 +1,48 @@
+from skyflow.error import SkyflowError
+from skyflow import Env, Skyflow, LogLevel
+from skyflow.vault.detect import DeidentifyFileRequest, GetRunRequest, PollOptions
+from skyflow.utils.enums import DetectRunStatus
+
+
+def perform_deidentify_file():
+ try:
+ vault_config = {
+ 'vault_id': '',
+ 'cluster_id': '',
+ 'env': Env.PROD,
+ 'credentials': {'path': ''},
+ }
+
+ skyflow_client = (
+ Skyflow.builder()
+ .add_vault_config(vault_config)
+ .set_log_level(LogLevel.ERROR)
+ .build()
+ )
+
+ request = DeidentifyFileRequest(
+ file_path='',
+ configuration_id='',
+ poll_options=PollOptions(wait_time=64),
+ output_directory='',
+ )
+
+ response = skyflow_client.detect().deidentify_file(request)
+
+ print(response.run_id, response.status)
+ if response.status == DetectRunStatus.SUCCESS:
+ print(response.metrics.pages)
+ elif response.status in (DetectRunStatus.IN_PROGRESS, DetectRunStatus.QUEUED):
+ run = skyflow_client.detect().get_run(GetRunRequest(run_id=response.run_id))
+ print(run.status)
+
+ except SkyflowError as error:
+ print('Skyflow Specific Error: ', {
+ 'code': error.http_code,
+ 'message': error.message,
+ 'details': error.details,
+ })
+
+
+if __name__ == '__main__':
+ perform_deidentify_file()
diff --git a/flowvault/samples/detect_api/deidentify_string.py b/flowvault/samples/detect_api/deidentify_string.py
new file mode 100644
index 00000000..a6058740
--- /dev/null
+++ b/flowvault/samples/detect_api/deidentify_string.py
@@ -0,0 +1,42 @@
+from skyflow.error import SkyflowError
+from skyflow import Env, Skyflow, LogLevel
+from skyflow.vault.detect import DeidentifyStringRequest
+
+
+def perform_deidentify_string():
+ try:
+ vault_config = {
+ 'vault_id': '',
+ 'cluster_id': '',
+ 'env': Env.PROD,
+ 'credentials': {'path': ''},
+ }
+
+ skyflow_client = (
+ Skyflow.builder()
+ .add_vault_config(vault_config)
+ .set_log_level(LogLevel.ERROR)
+ .build()
+ )
+
+ request = DeidentifyStringRequest(
+ text='My name is John Doe, and my email is johndoe@acme.com.',
+ configuration_id='',
+ )
+
+ response = skyflow_client.detect().deidentify_string(request)
+
+ print(response.processed_text)
+ for entity in response.entities:
+ print(entity.entity_type, entity.token, entity.entity_scores)
+
+ except SkyflowError as error:
+ print('Skyflow Specific Error: ', {
+ 'code': error.http_code,
+ 'message': error.message,
+ 'details': error.details,
+ })
+
+
+if __name__ == '__main__':
+ perform_deidentify_string()
diff --git a/flowvault/samples/detect_api/get_run.py b/flowvault/samples/detect_api/get_run.py
new file mode 100644
index 00000000..39a84dbf
--- /dev/null
+++ b/flowvault/samples/detect_api/get_run.py
@@ -0,0 +1,39 @@
+from skyflow.error import SkyflowError
+from skyflow import Env, Skyflow, LogLevel
+from skyflow.vault.detect import GetRunRequest
+from skyflow.utils.enums import DetectRunStatus
+
+
+def perform_get_run():
+ try:
+ vault_config = {
+ 'vault_id': '',
+ 'cluster_id': '',
+ 'env': Env.PROD,
+ 'credentials': {'path': ''},
+ }
+
+ skyflow_client = (
+ Skyflow.builder()
+ .add_vault_config(vault_config)
+ .set_log_level(LogLevel.ERROR)
+ .build()
+ )
+
+ response = skyflow_client.detect().get_run(GetRunRequest(run_id=''))
+
+ print(response.run_id, response.status)
+ if response.status == DetectRunStatus.SUCCESS:
+ for output in response.output:
+ print(output.processed_file_type, output.processed_file_extension)
+
+ except SkyflowError as error:
+ print('Skyflow Specific Error: ', {
+ 'code': error.http_code,
+ 'message': error.message,
+ 'details': error.details,
+ })
+
+
+if __name__ == '__main__':
+ perform_get_run()
diff --git a/flowvault/samples/detect_api/reidentify_file.py b/flowvault/samples/detect_api/reidentify_file.py
new file mode 100644
index 00000000..9214cc7e
--- /dev/null
+++ b/flowvault/samples/detect_api/reidentify_file.py
@@ -0,0 +1,58 @@
+import base64
+
+from skyflow.error import SkyflowError
+from skyflow import Env, Skyflow, LogLevel
+from skyflow.vault.detect import ReidentifyFileRequest, RedactionLevel
+from skyflow.utils.enums import ReidentifySourceType, FileDataFormat, DetectRunStatus
+
+
+def perform_reidentify_file():
+ try:
+ vault_config = {
+ 'vault_id': '',
+ 'cluster_id': '',
+ 'env': Env.PROD,
+ 'credentials': {'path': ''},
+ }
+
+ skyflow_client = (
+ Skyflow.builder()
+ .add_vault_config(vault_config)
+ .set_log_level(LogLevel.ERROR)
+ .build()
+ )
+
+ with open('', 'rb') as handle:
+ encoded = base64.b64encode(handle.read()).decode('utf-8')
+
+ request = ReidentifyFileRequest(
+ data_source=ReidentifySourceType.BASE64,
+ value=encoded,
+ data_format=FileDataFormat.TXT,
+ redaction_level=[
+ RedactionLevel(
+ token_group_name='',
+ redaction_pattern='',
+ ),
+ ],
+ )
+
+ response = skyflow_client.detect().reidentify_file(request)
+
+ print(response.status)
+ if response.status == DetectRunStatus.SUCCESS:
+ for index, output in enumerate(response.output):
+ extension = output.processed_file_extension.value if output.processed_file_extension else 'txt'
+ with open(f'reidentified-{index}.{extension}', 'wb') as out:
+ out.write(base64.b64decode(output.processed_file))
+
+ except SkyflowError as error:
+ print('Skyflow Specific Error: ', {
+ 'code': error.http_code,
+ 'message': error.message,
+ 'details': error.details,
+ })
+
+
+if __name__ == '__main__':
+ perform_reidentify_file()
diff --git a/flowvault/samples/detect_api/reidentify_string.py b/flowvault/samples/detect_api/reidentify_string.py
new file mode 100644
index 00000000..bc898de4
--- /dev/null
+++ b/flowvault/samples/detect_api/reidentify_string.py
@@ -0,0 +1,45 @@
+from skyflow.error import SkyflowError
+from skyflow import Env, Skyflow, LogLevel
+from skyflow.vault.detect import ReidentifyStringRequest, RedactionLevel
+
+
+def perform_reidentify_string():
+ try:
+ vault_config = {
+ 'vault_id': '',
+ 'cluster_id': '',
+ 'env': Env.PROD,
+ 'credentials': {'path': ''},
+ }
+
+ skyflow_client = (
+ Skyflow.builder()
+ .add_vault_config(vault_config)
+ .set_log_level(LogLevel.ERROR)
+ .build()
+ )
+
+ request = ReidentifyStringRequest(
+ text='My name is [NAME_1].',
+ redaction_level=[
+ RedactionLevel(
+ token_group_name='',
+ redaction_pattern='',
+ ),
+ ],
+ )
+
+ response = skyflow_client.detect().reidentify_string(request)
+
+ print(response.processed_text)
+
+ except SkyflowError as error:
+ print('Skyflow Specific Error: ', {
+ 'code': error.http_code,
+ 'message': error.message,
+ 'details': error.details,
+ })
+
+
+if __name__ == '__main__':
+ perform_reidentify_string()
diff --git a/flowvault/skyflow/client/skyflow.py b/flowvault/skyflow/client/skyflow.py
index abce354c..ccc4006e 100644
--- a/flowvault/skyflow/client/skyflow.py
+++ b/flowvault/skyflow/client/skyflow.py
@@ -4,10 +4,12 @@
from skyflow.utils.validations import validate_vault_config, validate_update_vault_config
from skyflow.vault.client.client import VaultClient
from skyflow.vault.controller import VaultController
+from skyflow.vault.detect import DetectController
Skyflow = make_skyflow_class(
vault_client_cls=VaultClient,
vault_controller_cls=VaultController,
+ detect_cls=DetectController,
skyflow_messages=SkyflowMessages,
validate_vault_config=validate_vault_config,
validate_update_vault_config=validate_update_vault_config,
diff --git a/flowvault/skyflow/utils/enums/__init__.py b/flowvault/skyflow/utils/enums/__init__.py
index 8bd9d9d4..89dbcfb5 100644
--- a/flowvault/skyflow/utils/enums/__init__.py
+++ b/flowvault/skyflow/utils/enums/__init__.py
@@ -2,3 +2,19 @@
from ._env_urls import EnvUrls
from ._custom_header_key import CustomHeaderKey
from ._file_upload_status import FileUploadStatus
+from ._deidentify_source_type import DeidentifySourceType
+from ._reidentify_source_type import ReidentifySourceType
+from common.utils.enums.redaction_type import RedactionType
+from common.utils.enums.detect import (
+ DeidentificationType,
+ DetectRunStatus,
+ EntityType,
+ FileDataFormat,
+ GuardrailsValidation,
+ MaskingMethod,
+ ObjectDeidentificationType,
+ ObjectEntityType,
+ OutputTranscriptionType,
+ PdfProcessingMode,
+ ReturnEntitiesType,
+)
diff --git a/flowvault/skyflow/utils/enums/_deidentify_source_type.py b/flowvault/skyflow/utils/enums/_deidentify_source_type.py
new file mode 100644
index 00000000..7635964a
--- /dev/null
+++ b/flowvault/skyflow/utils/enums/_deidentify_source_type.py
@@ -0,0 +1,6 @@
+from enum import Enum
+
+
+class DeidentifySourceType(Enum):
+ BASE64 = "BASE64"
+ PRESIGNED_URL = "PRESIGNED_URL"
diff --git a/flowvault/skyflow/utils/enums/_reidentify_source_type.py b/flowvault/skyflow/utils/enums/_reidentify_source_type.py
new file mode 100644
index 00000000..8bce69da
--- /dev/null
+++ b/flowvault/skyflow/utils/enums/_reidentify_source_type.py
@@ -0,0 +1,6 @@
+from enum import Enum
+
+
+class ReidentifySourceType(Enum):
+ BASE64 = "BASE64"
+ PRESIGNED_URL = "PRESIGNED_URL"
diff --git a/flowvault/skyflow/vault/client/client.py b/flowvault/skyflow/vault/client/client.py
index 994e4c59..4154c2ff 100644
--- a/flowvault/skyflow/vault/client/client.py
+++ b/flowvault/skyflow/vault/client/client.py
@@ -1,8 +1,9 @@
import httpx
from common.vault.base_vault_client import BaseVaultClient
+from common.generated.rest.client import SkyflowAuth as DetectSkyflowAuth
from skyflow.generated.rest.client import SkyflowAuth
-from skyflow.utils import get_vault_url
+from skyflow.utils import get_vault_url, get_metrics
from skyflow.utils._http_config import (
TIMEOUT_KEY,
CONNECT_TIMEOUT_KEY,
@@ -35,6 +36,7 @@ def __init__(self, config):
self._common_http_config = {}
self._sync_httpx_client = None
self._sync_upload_client = None
+ self._detect_api_client = None
def set_common_http_config(self, common_http_config):
self._common_http_config = common_http_config or {}
@@ -89,6 +91,7 @@ def initialize_api_client(self, vault_url, bearer_token):
transport=httpx.HTTPTransport(limits=limits),
)
self._api_client = SkyflowAuth(base_url=vault_url, token=bearer_token or "", httpx_client=sync_client)
+ self._detect_api_client = DetectSkyflowAuth(base_url=vault_url, token=bearer_token or "", httpx_client=sync_client)
def close(self):
self.__close_httpx_clients()
@@ -103,6 +106,7 @@ def __close_httpx_clients(self):
except Exception:
pass
setattr(self, attribute, None)
+ self._detect_api_client = None
def get_records_api(self):
return self._api_client.records
@@ -116,6 +120,26 @@ def get_query_api(self):
def get_files_api(self):
return self._api_client.files
+ def get_strings_v2_api(self):
+ return self._detect_api_client.strings_v2
+
+ def get_files_v2_api(self):
+ return self._detect_api_client.files_v2
+
+ def get_guardrails_v2_api(self):
+ return self._detect_api_client.guardrails_v2
+
+ def get_deidentify_source_type(self):
+ from skyflow.utils.enums import DeidentifySourceType
+ return DeidentifySourceType
+
+ def get_reidentify_source_type(self):
+ from skyflow.utils.enums import ReidentifySourceType
+ return ReidentifySourceType
+
+ def get_sdk_metrics(self):
+ return get_metrics()
+
def put_signed_url(self, signed_url, content, content_type=None):
headers = {}
if content_type:
diff --git a/flowvault/skyflow/vault/detect/__init__.py b/flowvault/skyflow/vault/detect/__init__.py
new file mode 100644
index 00000000..15517bb2
--- /dev/null
+++ b/flowvault/skyflow/vault/detect/__init__.py
@@ -0,0 +1,36 @@
+from common.vault.detect import (
+ DetectController,
+ Audio,
+ Bleep,
+ CheckGuardrailsRequest,
+ CheckGuardrailsResponse,
+ CustomType,
+ DeidentifyFileRequest,
+ DeidentifyFileResponse,
+ DeidentifyStringRequest,
+ DeidentifyStringResponse,
+ Detect,
+ DetectConfiguration,
+ DetectedEntity,
+ Document,
+ Entity,
+ EntityLocation,
+ FileMapping,
+ FileOutput,
+ GetRunRequest,
+ GetRunResponse,
+ Image,
+ Media,
+ Metrics,
+ ObjectEntity,
+ Pdf,
+ PollOptions,
+ ReidentifyFileRequest,
+ ReidentifyFileResponse,
+ ReidentifyStringRequest,
+ ReidentifyStringResponse,
+ ShiftDates,
+ Transformation,
+)
+
+from ._redaction_level import RedactionLevel
diff --git a/flowvault/skyflow/vault/detect/_redaction_level.py b/flowvault/skyflow/vault/detect/_redaction_level.py
new file mode 100644
index 00000000..29a2a7fe
--- /dev/null
+++ b/flowvault/skyflow/vault/detect/_redaction_level.py
@@ -0,0 +1,14 @@
+from common.vault.detect import RedactionRule
+
+
+class RedactionLevel(RedactionRule):
+ def __init__(self, token_group_name: str = None,
+ redaction_pattern: str = None):
+ self.token_group_name = token_group_name
+ self.redaction_pattern = redaction_pattern
+
+ def _api_token_group_name(self):
+ return self.token_group_name
+
+ def _api_redaction_pattern(self):
+ return self.redaction_pattern
diff --git a/flowvault/tests/client/test_skyflow.py b/flowvault/tests/client/test_skyflow.py
index 84164b47..6a605e57 100644
--- a/flowvault/tests/client/test_skyflow.py
+++ b/flowvault/tests/client/test_skyflow.py
@@ -92,11 +92,16 @@ def test_vault_returns_vault_controller(self):
vault = client.vault("VAULT_ID")
self.assertTrue(hasattr(vault, "insert"))
+ def test_detect_returns_detect_controller(self):
+ client = self.builder.add_vault_config(VALID_VAULT_CONFIG).build()
+ detect = client.detect("VAULT_ID")
+ self.assertTrue(hasattr(detect, "deidentify_string"))
+
-class TestConnectionAndDetectNotSupported(unittest.TestCase):
- """flowvault has no Connection/Detect concept this round -- ConnectionMixin/DetectMixin are
- only added to a variant's produced Skyflow class when connection_cls/detect_cls are supplied,
- so these methods are genuinely absent here (AttributeError), unlike v2 where they work."""
+class TestConnectionNotSupported(unittest.TestCase):
+ """flowvault has no Connection concept this round -- ConnectionMixin is only added to a
+ variant's produced Skyflow class when connection_cls is supplied, so these methods are
+ genuinely absent here (AttributeError)."""
def setUp(self):
self.client = Skyflow.builder().add_vault_config(VALID_VAULT_CONFIG).build()
@@ -105,10 +110,6 @@ def test_connection_raises(self):
with self.assertRaises(AttributeError):
self.client.connection()
- def test_detect_raises(self):
- with self.assertRaises(AttributeError):
- self.client.detect()
-
def test_add_connection_config_raises(self):
with self.assertRaises(AttributeError):
self.client.add_connection_config({})
diff --git a/flowvault/tests/vault/detect/__init__.py b/flowvault/tests/vault/detect/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/flowvault/tests/vault/detect/test_reexports.py b/flowvault/tests/vault/detect/test_reexports.py
new file mode 100644
index 00000000..ddff0965
--- /dev/null
+++ b/flowvault/tests/vault/detect/test_reexports.py
@@ -0,0 +1,48 @@
+import unittest
+
+
+class TestDetectReexports(unittest.TestCase):
+ def test_models_import_from_vault_detect(self):
+ from skyflow.vault.detect import (
+ DeidentifyStringRequest,
+ DeidentifyFileRequest,
+ GetRunRequest,
+ ReidentifyStringRequest,
+ ReidentifyFileRequest,
+ CheckGuardrailsRequest,
+ PollOptions,
+ DetectConfiguration,
+ Detect,
+ Entity,
+ RedactionLevel,
+ )
+
+ request = DeidentifyStringRequest(text="hello", configuration_id="cfg")
+ self.assertEqual(request.text, "hello")
+ self.assertIsNone(PollOptions().wait_time)
+
+ def test_enums_import_from_utils_enums(self):
+ from skyflow.utils.enums import (
+ EntityType,
+ DeidentificationType,
+ ReturnEntitiesType,
+ RedactionType,
+ DeidentifySourceType,
+ ReidentifySourceType,
+ FileDataFormat,
+ DetectRunStatus,
+ ObjectEntityType,
+ ObjectDeidentificationType,
+ OutputTranscriptionType,
+ PdfProcessingMode,
+ MaskingMethod,
+ GuardrailsValidation,
+ )
+
+ self.assertEqual(EntityType.NAME.value, "NAME")
+ self.assertEqual(FileDataFormat.PDF.value, "pdf")
+ self.assertEqual(DetectRunStatus.SUCCESS.value, "SUCCESS")
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/skyvault/MANIFEST.in b/skyvault/MANIFEST.in
index 05007153..628838b0 100644
--- a/skyvault/MANIFEST.in
+++ b/skyvault/MANIFEST.in
@@ -1 +1,4 @@
+graft common
prune samples
+global-exclude *.pyc
+global-exclude __pycache__
diff --git a/skyvault/api-report/skyflow.api.json b/skyvault/api-report/skyflow.api.json
index 0f281682..69bb3be0 100644
--- a/skyvault/api-report/skyflow.api.json
+++ b/skyvault/api-report/skyflow.api.json
@@ -32,6 +32,16 @@
"skyflow.utils.enums.ContentType.PLAINTEXT": "attr = 'text/plain'",
"skyflow.utils.enums.ContentType.URLENCODED": "attr = 'application/x-www-form-urlencoded'",
"skyflow.utils.enums.ContentType.XML": "attr = 'text/xml'",
+ "skyflow.utils.enums.DeidentificationType": "class (Enum)",
+ "skyflow.utils.enums.DeidentificationType.ENTITY_ONLY": "attr = 'ENTITY_ONLY'",
+ "skyflow.utils.enums.DeidentificationType.ENTITY_UNIQUE_COUNTER": "attr = 'ENTITY_UNIQUE_COUNTER'",
+ "skyflow.utils.enums.DeidentificationType.MASK": "attr = 'MASK'",
+ "skyflow.utils.enums.DeidentificationType.UNKNOWN": "attr = 'UNKNOWN'",
+ "skyflow.utils.enums.DeidentificationType.VAULT_TOKEN": "attr = 'VAULT_TOKEN'",
+ "skyflow.utils.enums.DeidentifySourceType": "class (Enum)",
+ "skyflow.utils.enums.DeidentifySourceType.BASE64": "attr = 'BASE64'",
+ "skyflow.utils.enums.DeidentifySourceType.PRESIGNED_URL": "attr = 'PRESIGNED_URL'",
+ "skyflow.utils.enums.DeidentifySourceType.SKYFLOW_ID": "attr = 'SKYFLOW_ID'",
"skyflow.utils.enums.DetectEntities": "class (Enum)",
"skyflow.utils.enums.DetectEntities.ACCOUNT_NUMBER": "attr = 'account_number'",
"skyflow.utils.enums.DetectEntities.AGE": "attr = 'age'",
@@ -109,6 +119,84 @@
"skyflow.utils.enums.DetectOutputTranscriptions.MEDICAL_TRANSCRIPTION": "attr = 'medical_transcription'",
"skyflow.utils.enums.DetectOutputTranscriptions.PLAINTEXT_TRANSCRIPTION": "attr = 'plaintext_transcription'",
"skyflow.utils.enums.DetectOutputTranscriptions.TRANSCRIPTION": "attr = 'transcription'",
+ "skyflow.utils.enums.DetectRunStatus": "class (Enum)",
+ "skyflow.utils.enums.DetectRunStatus.FAILED": "attr = 'FAILED'",
+ "skyflow.utils.enums.DetectRunStatus.IN_PROGRESS": "attr = 'IN_PROGRESS'",
+ "skyflow.utils.enums.DetectRunStatus.QUEUED": "attr = 'QUEUED'",
+ "skyflow.utils.enums.DetectRunStatus.SUCCESS": "attr = 'SUCCESS'",
+ "skyflow.utils.enums.DetectRunStatus.UNKNOWN": "attr = 'UNKNOWN'",
+ "skyflow.utils.enums.EntityType": "class (Enum)",
+ "skyflow.utils.enums.EntityType.ACCOUNT_NUMBER": "attr = 'ACCOUNT_NUMBER'",
+ "skyflow.utils.enums.EntityType.AGE": "attr = 'AGE'",
+ "skyflow.utils.enums.EntityType.ALL": "attr = 'ALL'",
+ "skyflow.utils.enums.EntityType.BANK_ACCOUNT": "attr = 'BANK_ACCOUNT'",
+ "skyflow.utils.enums.EntityType.BLOOD_TYPE": "attr = 'BLOOD_TYPE'",
+ "skyflow.utils.enums.EntityType.CONDITION": "attr = 'CONDITION'",
+ "skyflow.utils.enums.EntityType.CORPORATE_ACTION": "attr = 'CORPORATE_ACTION'",
+ "skyflow.utils.enums.EntityType.CREDIT_CARD": "attr = 'CREDIT_CARD'",
+ "skyflow.utils.enums.EntityType.CREDIT_CARD_EXPIRATION": "attr = 'CREDIT_CARD_EXPIRATION'",
+ "skyflow.utils.enums.EntityType.CVV": "attr = 'CVV'",
+ "skyflow.utils.enums.EntityType.DATE": "attr = 'DATE'",
+ "skyflow.utils.enums.EntityType.DATE_INTERVAL": "attr = 'DATE_INTERVAL'",
+ "skyflow.utils.enums.EntityType.DAY": "attr = 'DAY'",
+ "skyflow.utils.enums.EntityType.DOB": "attr = 'DOB'",
+ "skyflow.utils.enums.EntityType.DOSE": "attr = 'DOSE'",
+ "skyflow.utils.enums.EntityType.DRIVER_LICENSE": "attr = 'DRIVER_LICENSE'",
+ "skyflow.utils.enums.EntityType.DRUG": "attr = 'DRUG'",
+ "skyflow.utils.enums.EntityType.DURATION": "attr = 'DURATION'",
+ "skyflow.utils.enums.EntityType.EFFECT": "attr = 'EFFECT'",
+ "skyflow.utils.enums.EntityType.EMAIL_ADDRESS": "attr = 'EMAIL_ADDRESS'",
+ "skyflow.utils.enums.EntityType.EVENT": "attr = 'EVENT'",
+ "skyflow.utils.enums.EntityType.FILENAME": "attr = 'FILENAME'",
+ "skyflow.utils.enums.EntityType.FINANCIAL_METRIC": "attr = 'FINANCIAL_METRIC'",
+ "skyflow.utils.enums.EntityType.GENDER": "attr = 'GENDER'",
+ "skyflow.utils.enums.EntityType.HEALTHCARE_NUMBER": "attr = 'HEALTHCARE_NUMBER'",
+ "skyflow.utils.enums.EntityType.INJURY": "attr = 'INJURY'",
+ "skyflow.utils.enums.EntityType.IP_ADDRESS": "attr = 'IP_ADDRESS'",
+ "skyflow.utils.enums.EntityType.LANGUAGE": "attr = 'LANGUAGE'",
+ "skyflow.utils.enums.EntityType.LOCATION": "attr = 'LOCATION'",
+ "skyflow.utils.enums.EntityType.LOCATION_ADDRESS": "attr = 'LOCATION_ADDRESS'",
+ "skyflow.utils.enums.EntityType.LOCATION_ADDRESS_STREET": "attr = 'LOCATION_ADDRESS_STREET'",
+ "skyflow.utils.enums.EntityType.LOCATION_CITY": "attr = 'LOCATION_CITY'",
+ "skyflow.utils.enums.EntityType.LOCATION_COORDINATE": "attr = 'LOCATION_COORDINATE'",
+ "skyflow.utils.enums.EntityType.LOCATION_COUNTRY": "attr = 'LOCATION_COUNTRY'",
+ "skyflow.utils.enums.EntityType.LOCATION_STATE": "attr = 'LOCATION_STATE'",
+ "skyflow.utils.enums.EntityType.LOCATION_ZIP": "attr = 'LOCATION_ZIP'",
+ "skyflow.utils.enums.EntityType.MARITAL_STATUS": "attr = 'MARITAL_STATUS'",
+ "skyflow.utils.enums.EntityType.MEDICAL_CODE": "attr = 'MEDICAL_CODE'",
+ "skyflow.utils.enums.EntityType.MEDICAL_PROCESS": "attr = 'MEDICAL_PROCESS'",
+ "skyflow.utils.enums.EntityType.MONEY": "attr = 'MONEY'",
+ "skyflow.utils.enums.EntityType.MONTH": "attr = 'MONTH'",
+ "skyflow.utils.enums.EntityType.NAME": "attr = 'NAME'",
+ "skyflow.utils.enums.EntityType.NAME_FAMILY": "attr = 'NAME_FAMILY'",
+ "skyflow.utils.enums.EntityType.NAME_GIVEN": "attr = 'NAME_GIVEN'",
+ "skyflow.utils.enums.EntityType.NAME_MEDICAL_PROFESSIONAL": "attr = 'NAME_MEDICAL_PROFESSIONAL'",
+ "skyflow.utils.enums.EntityType.NONE": "attr = 'NONE'",
+ "skyflow.utils.enums.EntityType.NUMERICAL_PII": "attr = 'NUMERICAL_PII'",
+ "skyflow.utils.enums.EntityType.OCCUPATION": "attr = 'OCCUPATION'",
+ "skyflow.utils.enums.EntityType.ORGANIZATION": "attr = 'ORGANIZATION'",
+ "skyflow.utils.enums.EntityType.ORGANIZATION_ID": "attr = 'ORGANIZATION_ID'",
+ "skyflow.utils.enums.EntityType.ORGANIZATION_MEDICAL_FACILITY": "attr = 'ORGANIZATION_MEDICAL_FACILITY'",
+ "skyflow.utils.enums.EntityType.ORIGIN": "attr = 'ORIGIN'",
+ "skyflow.utils.enums.EntityType.PASSPORT_NUMBER": "attr = 'PASSPORT_NUMBER'",
+ "skyflow.utils.enums.EntityType.PASSWORD": "attr = 'PASSWORD'",
+ "skyflow.utils.enums.EntityType.PHONE_NUMBER": "attr = 'PHONE_NUMBER'",
+ "skyflow.utils.enums.EntityType.PHYSICAL_ATTRIBUTE": "attr = 'PHYSICAL_ATTRIBUTE'",
+ "skyflow.utils.enums.EntityType.POLITICAL_AFFILIATION": "attr = 'POLITICAL_AFFILIATION'",
+ "skyflow.utils.enums.EntityType.PRODUCT": "attr = 'PRODUCT'",
+ "skyflow.utils.enums.EntityType.PROJECT": "attr = 'PROJECT'",
+ "skyflow.utils.enums.EntityType.RELIGION": "attr = 'RELIGION'",
+ "skyflow.utils.enums.EntityType.ROUTING_NUMBER": "attr = 'ROUTING_NUMBER'",
+ "skyflow.utils.enums.EntityType.SEXUALITY": "attr = 'SEXUALITY'",
+ "skyflow.utils.enums.EntityType.SSN": "attr = 'SSN'",
+ "skyflow.utils.enums.EntityType.STATISTICS": "attr = 'STATISTICS'",
+ "skyflow.utils.enums.EntityType.TIME": "attr = 'TIME'",
+ "skyflow.utils.enums.EntityType.TREND": "attr = 'TREND'",
+ "skyflow.utils.enums.EntityType.URL": "attr = 'URL'",
+ "skyflow.utils.enums.EntityType.USERNAME": "attr = 'USERNAME'",
+ "skyflow.utils.enums.EntityType.VEHICLE_ID": "attr = 'VEHICLE_ID'",
+ "skyflow.utils.enums.EntityType.YEAR": "attr = 'YEAR'",
+ "skyflow.utils.enums.EntityType.ZODIAC_SIGN": "attr = 'ZODIAC_SIGN'",
"skyflow.utils.enums.Env": "class (Enum)",
"skyflow.utils.enums.Env.DEV": "attr = 'DEV'",
"skyflow.utils.enums.Env.PROD": "attr = 'PROD'",
@@ -119,6 +207,34 @@
"skyflow.utils.enums.EnvUrls.PROD": "attr = 'vault.skyflowapis.com'",
"skyflow.utils.enums.EnvUrls.SANDBOX": "attr = 'vault.skyflowapis-preview.com'",
"skyflow.utils.enums.EnvUrls.STAGE": "attr = 'vault.skyflowapis.tech'",
+ "skyflow.utils.enums.FileDataFormat": "class (Enum)",
+ "skyflow.utils.enums.FileDataFormat.BMP": "attr = 'bmp'",
+ "skyflow.utils.enums.FileDataFormat.CSV": "attr = 'csv'",
+ "skyflow.utils.enums.FileDataFormat.DCM": "attr = 'dcm'",
+ "skyflow.utils.enums.FileDataFormat.DOC": "attr = 'doc'",
+ "skyflow.utils.enums.FileDataFormat.DOCX": "attr = 'docx'",
+ "skyflow.utils.enums.FileDataFormat.GIF": "attr = 'gif'",
+ "skyflow.utils.enums.FileDataFormat.JPEG": "attr = 'jpeg'",
+ "skyflow.utils.enums.FileDataFormat.JPG": "attr = 'jpg'",
+ "skyflow.utils.enums.FileDataFormat.JSON": "attr = 'json'",
+ "skyflow.utils.enums.FileDataFormat.JSONL": "attr = 'jsonl'",
+ "skyflow.utils.enums.FileDataFormat.MP3": "attr = 'mp3'",
+ "skyflow.utils.enums.FileDataFormat.PDF": "attr = 'pdf'",
+ "skyflow.utils.enums.FileDataFormat.PNG": "attr = 'png'",
+ "skyflow.utils.enums.FileDataFormat.PPT": "attr = 'ppt'",
+ "skyflow.utils.enums.FileDataFormat.PPTX": "attr = 'pptx'",
+ "skyflow.utils.enums.FileDataFormat.TIF": "attr = 'tif'",
+ "skyflow.utils.enums.FileDataFormat.TIFF": "attr = 'tiff'",
+ "skyflow.utils.enums.FileDataFormat.TXT": "attr = 'txt'",
+ "skyflow.utils.enums.FileDataFormat.WAV": "attr = 'wav'",
+ "skyflow.utils.enums.FileDataFormat.XLS": "attr = 'xls'",
+ "skyflow.utils.enums.FileDataFormat.XLSX": "attr = 'xlsx'",
+ "skyflow.utils.enums.FileDataFormat.XML": "attr = 'xml'",
+ "skyflow.utils.enums.FileDataFormat.ZIP": "attr = 'zip'",
+ "skyflow.utils.enums.GuardrailsValidation": "class (Enum)",
+ "skyflow.utils.enums.GuardrailsValidation.FAILED": "attr = 'FAILED'",
+ "skyflow.utils.enums.GuardrailsValidation.PASSED": "attr = 'PASSED'",
+ "skyflow.utils.enums.GuardrailsValidation.UNKNOWN": "attr = 'UNKNOWN'",
"skyflow.utils.enums.LogLevel": "class (Enum)",
"skyflow.utils.enums.LogLevel.DEBUG": "attr = 1",
"skyflow.utils.enums.LogLevel.ERROR": "attr = 4",
@@ -126,19 +242,48 @@
"skyflow.utils.enums.LogLevel.OFF": "attr = 5",
"skyflow.utils.enums.LogLevel.WARN": "attr = 3",
"skyflow.utils.enums.MaskingMethod": "class (Enum)",
- "skyflow.utils.enums.MaskingMethod.BLACKBOX": "attr = 'blackbox'",
- "skyflow.utils.enums.MaskingMethod.BLUR": "attr = 'blur'",
+ "skyflow.utils.enums.MaskingMethod.BLACKBOX": "attr = 'BLACKBOX'",
+ "skyflow.utils.enums.MaskingMethod.BLUR": "attr = 'BLUR'",
+ "skyflow.utils.enums.MaskingMethod.NONE": "attr = 'NONE'",
+ "skyflow.utils.enums.ObjectDeidentificationType": "class (Enum)",
+ "skyflow.utils.enums.ObjectDeidentificationType.REDACT": "attr = 'REDACT'",
+ "skyflow.utils.enums.ObjectDeidentificationType.UNKNOWN": "attr = 'UNKNOWN'",
+ "skyflow.utils.enums.ObjectDeidentificationType.UNREDACT": "attr = 'UNREDACT'",
+ "skyflow.utils.enums.ObjectEntityType": "class (Enum)",
+ "skyflow.utils.enums.ObjectEntityType.ALL": "attr = 'ALL'",
+ "skyflow.utils.enums.ObjectEntityType.FACE": "attr = 'FACE'",
+ "skyflow.utils.enums.ObjectEntityType.LICENSE_PLATE": "attr = 'LICENSE_PLATE'",
+ "skyflow.utils.enums.ObjectEntityType.LOGO": "attr = 'LOGO'",
+ "skyflow.utils.enums.ObjectEntityType.NONE": "attr = 'NONE'",
+ "skyflow.utils.enums.ObjectEntityType.SIGNATURE": "attr = 'SIGNATURE'",
+ "skyflow.utils.enums.OutputTranscriptionType": "class (Enum)",
+ "skyflow.utils.enums.OutputTranscriptionType.DIARIZED_TRANSCRIPTION": "attr = 'DIARIZED_TRANSCRIPTION'",
+ "skyflow.utils.enums.OutputTranscriptionType.MEDICAL_DIARIZED_TRANSCRIPTION": "attr = 'MEDICAL_DIARIZED_TRANSCRIPTION'",
+ "skyflow.utils.enums.OutputTranscriptionType.MEDICAL_TRANSCRIPTION": "attr = 'MEDICAL_TRANSCRIPTION'",
+ "skyflow.utils.enums.OutputTranscriptionType.NONE": "attr = 'NONE'",
+ "skyflow.utils.enums.OutputTranscriptionType.TRANSCRIPTION": "attr = 'TRANSCRIPTION'",
+ "skyflow.utils.enums.PdfProcessingMode": "class (Enum)",
+ "skyflow.utils.enums.PdfProcessingMode.NONE": "attr = 'NONE'",
+ "skyflow.utils.enums.PdfProcessingMode.OCR": "attr = 'OCR'",
+ "skyflow.utils.enums.PdfProcessingMode.TEXT_LAYER": "attr = 'TEXT_LAYER'",
"skyflow.utils.enums.RedactionType": "class (Enum)",
"skyflow.utils.enums.RedactionType.DEFAULT": "attr = 'DEFAULT'",
"skyflow.utils.enums.RedactionType.MASKED": "attr = 'MASKED'",
"skyflow.utils.enums.RedactionType.PLAIN_TEXT": "attr = 'PLAIN_TEXT'",
"skyflow.utils.enums.RedactionType.REDACTED": "attr = 'REDACTED'",
+ "skyflow.utils.enums.ReidentifySourceType": "class (Enum)",
+ "skyflow.utils.enums.ReidentifySourceType.BASE64": "attr = 'BASE64'",
+ "skyflow.utils.enums.ReidentifySourceType.PRESIGNED_URL": "attr = 'PRESIGNED_URL'",
"skyflow.utils.enums.RequestMethod": "class (Enum)",
"skyflow.utils.enums.RequestMethod.DELETE": "attr = 'DELETE'",
"skyflow.utils.enums.RequestMethod.GET": "attr = 'GET'",
"skyflow.utils.enums.RequestMethod.NONE": "attr = 'NONE'",
"skyflow.utils.enums.RequestMethod.POST": "attr = 'POST'",
"skyflow.utils.enums.RequestMethod.PUT": "attr = 'PUT'",
+ "skyflow.utils.enums.ReturnEntitiesType": "class (Enum)",
+ "skyflow.utils.enums.ReturnEntitiesType.ALL": "attr = 'ALL'",
+ "skyflow.utils.enums.ReturnEntitiesType.EXCLUDE_SENSITIVE_DATA": "attr = 'EXCLUDE_SENSITIVE_DATA'",
+ "skyflow.utils.enums.ReturnEntitiesType.NONE": "attr = 'NONE'",
"skyflow.utils.enums.TokenMode": "class (Enum)",
"skyflow.utils.enums.TokenMode.DISABLE": "attr = 'DISABLE'",
"skyflow.utils.enums.TokenMode.ENABLE": "attr = 'ENABLE'",
@@ -162,12 +307,6 @@
"skyflow.vault.controller.Connection": "class ()",
"skyflow.vault.controller.Connection.__init__": "def (self, vault_client)",
"skyflow.vault.controller.Connection.invoke": "def (self, request: InvokeConnectionRequest)",
- "skyflow.vault.controller.Detect": "class ()",
- "skyflow.vault.controller.Detect.__init__": "def (self, vault_client)",
- "skyflow.vault.controller.Detect.deidentify_file": "def (self, request: DeidentifyFileRequest)",
- "skyflow.vault.controller.Detect.deidentify_text": "def (self, request: DeidentifyTextRequest) -> DeidentifyTextResponse",
- "skyflow.vault.controller.Detect.get_detect_run": "def (self, request: GetDetectRunRequest)",
- "skyflow.vault.controller.Detect.reidentify_text": "def (self, request: ReidentifyTextRequest) -> ReidentifyTextResponse",
"skyflow.vault.controller.Vault": "attr",
"skyflow.vault.controller.VaultController": "class (BaseVaultController)",
"skyflow.vault.controller.VaultController.__init__": "def (self, vault_client)",
@@ -244,104 +383,42 @@
"skyflow.vault.data.UpdateResponse.updated_field": "attr",
"skyflow.vault.data.UploadFileRequest": "class ()",
"skyflow.vault.data.UploadFileRequest.__init__": "def (self)",
- "skyflow.vault.detect.Bleep": "class ()",
- "skyflow.vault.detect.Bleep.__init__": "def (self, gain: Optional[float] = None, frequency: Optional[float] = None, start_padding: Optional[float] = None, stop_padding: Optional[float] = None)",
- "skyflow.vault.detect.Bleep.frequency": "attr",
- "skyflow.vault.detect.Bleep.gain": "attr",
- "skyflow.vault.detect.Bleep.start_padding": "attr",
- "skyflow.vault.detect.Bleep.stop_padding": "attr",
- "skyflow.vault.detect.DateTransformation": "class ()",
- "skyflow.vault.detect.DateTransformation.__init__": "def (self, max_days: int, min_days: int, entities: List[DetectEntities])",
- "skyflow.vault.detect.DateTransformation.entities": "attr",
- "skyflow.vault.detect.DateTransformation.max": "attr",
- "skyflow.vault.detect.DateTransformation.min": "attr",
- "skyflow.vault.detect.DeidentifyFileRequest": "class ()",
- "skyflow.vault.detect.DeidentifyFileRequest.__init__": "def (self, file = None, entities: Optional[List[DetectEntities]] = None, allow_regex_list: Optional[List[str]] = None, restrict_regex_list: Optional[List[str]] = None, token_format: Optional[TokenFormat] = None, transformations: Optional[Transformations] = None, output_processed_image: Optional[bool] = None, output_ocr_text: Optional[bool] = None, masking_method: Optional[MaskingMethod] = None, pixel_density: Optional[Union[int, float]] = None, max_resolution: Optional[Union[int, float]] = None, output_processed_audio: Optional[bool] = None, output_transcription: Optional[DetectOutputTranscriptions] = None, bleep: Optional[Bleep] = None, output_directory: Optional[str] = None, wait_time: Optional[Union[int, float]] = None)",
- "skyflow.vault.detect.DeidentifyFileRequest.allow_regex_list": "attr: Optional[List[str]]",
- "skyflow.vault.detect.DeidentifyFileRequest.bleep": "attr: Optional[Bleep]",
- "skyflow.vault.detect.DeidentifyFileRequest.entities": "attr: Optional[List[DetectEntities]]",
- "skyflow.vault.detect.DeidentifyFileRequest.file": "attr: FileInput",
- "skyflow.vault.detect.DeidentifyFileRequest.masking_method": "attr: Optional[MaskingMethod]",
- "skyflow.vault.detect.DeidentifyFileRequest.max_resolution": "attr: Optional[Union[int, float]]",
- "skyflow.vault.detect.DeidentifyFileRequest.output_directory": "attr: Optional[str]",
- "skyflow.vault.detect.DeidentifyFileRequest.output_ocr_text": "attr: Optional[bool]",
- "skyflow.vault.detect.DeidentifyFileRequest.output_processed_audio": "attr: Optional[bool]",
- "skyflow.vault.detect.DeidentifyFileRequest.output_processed_image": "attr: Optional[bool]",
- "skyflow.vault.detect.DeidentifyFileRequest.output_transcription": "attr: Optional[DetectOutputTranscriptions]",
- "skyflow.vault.detect.DeidentifyFileRequest.pixel_density": "attr: Optional[Union[int, float]]",
- "skyflow.vault.detect.DeidentifyFileRequest.restrict_regex_list": "attr: Optional[List[str]]",
- "skyflow.vault.detect.DeidentifyFileRequest.token_format": "attr: Optional[TokenFormat]",
- "skyflow.vault.detect.DeidentifyFileRequest.transformations": "attr: Optional[Transformations]",
- "skyflow.vault.detect.DeidentifyFileRequest.wait_time": "attr: Optional[Union[int, float]]",
- "skyflow.vault.detect.DeidentifyFileResponse": "class ()",
- "skyflow.vault.detect.DeidentifyFileResponse.__init__": "def (self, file_base64: Optional[str] = None, file: Optional[io.BytesIO] = None, type: Optional[str] = None, extension: Optional[str] = None, word_count: Optional[int] = None, char_count: Optional[int] = None, size_in_kb: Optional[float] = None, duration_in_seconds: Optional[float] = None, page_count: Optional[int] = None, slide_count: Optional[int] = None, entities: Optional[list] = None, run_id: Optional[str] = None, status: Optional[str] = None, errors: Optional[list] = None)",
- "skyflow.vault.detect.DeidentifyFileResponse.char_count": "attr",
- "skyflow.vault.detect.DeidentifyFileResponse.duration_in_seconds": "attr",
- "skyflow.vault.detect.DeidentifyFileResponse.entities": "attr",
- "skyflow.vault.detect.DeidentifyFileResponse.errors": "attr",
- "skyflow.vault.detect.DeidentifyFileResponse.extension": "attr",
- "skyflow.vault.detect.DeidentifyFileResponse.file": "attr",
- "skyflow.vault.detect.DeidentifyFileResponse.file_base64": "attr",
- "skyflow.vault.detect.DeidentifyFileResponse.page_count": "attr",
- "skyflow.vault.detect.DeidentifyFileResponse.run_id": "attr",
- "skyflow.vault.detect.DeidentifyFileResponse.size_in_kb": "attr",
- "skyflow.vault.detect.DeidentifyFileResponse.slide_count": "attr",
- "skyflow.vault.detect.DeidentifyFileResponse.status": "attr",
- "skyflow.vault.detect.DeidentifyFileResponse.type": "attr",
- "skyflow.vault.detect.DeidentifyFileResponse.word_count": "attr",
- "skyflow.vault.detect.DeidentifyTextRequest": "class ()",
- "skyflow.vault.detect.DeidentifyTextRequest.__init__": "def (self, text: str, entities: Optional[List[DetectEntities]] = None, allow_regex_list: Optional[List[str]] = None, restrict_regex_list: Optional[List[str]] = None, token_format: Optional[TokenFormat] = None, transformations: Optional[Transformations] = None)",
- "skyflow.vault.detect.DeidentifyTextRequest.allow_regex_list": "attr",
- "skyflow.vault.detect.DeidentifyTextRequest.entities": "attr",
- "skyflow.vault.detect.DeidentifyTextRequest.restrict_regex_list": "attr",
- "skyflow.vault.detect.DeidentifyTextRequest.text": "attr",
- "skyflow.vault.detect.DeidentifyTextRequest.token_format": "attr",
- "skyflow.vault.detect.DeidentifyTextRequest.transformations": "attr",
- "skyflow.vault.detect.DeidentifyTextResponse": "class ()",
- "skyflow.vault.detect.DeidentifyTextResponse.__init__": "def (self, processed_text: str, entities: List[EntityInfo], word_count: int, char_count: int, errors: Optional[list] = None)",
- "skyflow.vault.detect.DeidentifyTextResponse.char_count": "attr",
- "skyflow.vault.detect.DeidentifyTextResponse.entities": "attr",
- "skyflow.vault.detect.DeidentifyTextResponse.errors": "attr",
- "skyflow.vault.detect.DeidentifyTextResponse.processed_text": "attr",
- "skyflow.vault.detect.DeidentifyTextResponse.word_count": "attr",
- "skyflow.vault.detect.EntityInfo": "class ()",
- "skyflow.vault.detect.EntityInfo.__init__": "def (self, token: str, value: str, text_index: TextIndex, processed_index: TextIndex, entity: str, scores: Dict[str, float])",
- "skyflow.vault.detect.EntityInfo.entity": "attr",
- "skyflow.vault.detect.EntityInfo.processed_index": "attr",
- "skyflow.vault.detect.EntityInfo.scores": "attr",
- "skyflow.vault.detect.EntityInfo.text_index": "attr",
- "skyflow.vault.detect.EntityInfo.token": "attr",
- "skyflow.vault.detect.EntityInfo.value": "attr",
- "skyflow.vault.detect.FileInput": "class ()",
- "skyflow.vault.detect.FileInput.__init__": "def (self, file: BufferedReader = None, file_path: str = None)",
- "skyflow.vault.detect.FileInput.file": "attr",
- "skyflow.vault.detect.FileInput.file_path": "attr",
- "skyflow.vault.detect.GetDetectRunRequest": "class ()",
- "skyflow.vault.detect.GetDetectRunRequest.__init__": "def (self, run_id: str)",
- "skyflow.vault.detect.GetDetectRunRequest.run_id": "attr: str",
- "skyflow.vault.detect.ReidentifyTextRequest": "class ()",
- "skyflow.vault.detect.ReidentifyTextRequest.__init__": "def (self, text: str, redacted_entities: Optional[List[DetectEntities]] = None, masked_entities: Optional[List[DetectEntities]] = None, plain_text_entities: Optional[List[DetectEntities]] = None)",
- "skyflow.vault.detect.ReidentifyTextRequest.masked_entities": "attr",
- "skyflow.vault.detect.ReidentifyTextRequest.plain_text_entities": "attr",
- "skyflow.vault.detect.ReidentifyTextRequest.redacted_entities": "attr",
- "skyflow.vault.detect.ReidentifyTextRequest.text": "attr",
- "skyflow.vault.detect.ReidentifyTextResponse": "class ()",
- "skyflow.vault.detect.ReidentifyTextResponse.__init__": "def (self, processed_text: str, errors: Optional[list] = None)",
- "skyflow.vault.detect.ReidentifyTextResponse.errors": "attr",
- "skyflow.vault.detect.ReidentifyTextResponse.processed_text": "attr",
- "skyflow.vault.detect.TextIndex": "class ()",
- "skyflow.vault.detect.TextIndex.__init__": "def (self, start: int, end: int)",
- "skyflow.vault.detect.TextIndex.end": "attr",
- "skyflow.vault.detect.TextIndex.start": "attr",
- "skyflow.vault.detect.TokenFormat": "class ()",
- "skyflow.vault.detect.TokenFormat.__init__": "def (self, default: TokenType = TokenType.ENTITY_UNIQUE_COUNTER, vault_token: List[DetectEntities] = None, entity_unique_counter: List[DetectEntities] = None, entity_only: List[DetectEntities] = None)",
- "skyflow.vault.detect.TokenFormat.default": "attr",
- "skyflow.vault.detect.TokenFormat.entity_only": "attr",
- "skyflow.vault.detect.TokenFormat.entity_unique_counter": "attr",
- "skyflow.vault.detect.TokenFormat.vault_token": "attr",
- "skyflow.vault.detect.Transformations": "class ()",
- "skyflow.vault.detect.Transformations.__init__": "def (self, shift_dates: DateTransformation)",
- "skyflow.vault.detect.Transformations.shift_dates": "attr",
+ "skyflow.vault.detect.Audio": "alias -> common.vault.detect.Audio",
+ "skyflow.vault.detect.Bleep": "alias -> common.vault.detect.Bleep",
+ "skyflow.vault.detect.CheckGuardrailsRequest": "alias -> common.vault.detect.CheckGuardrailsRequest",
+ "skyflow.vault.detect.CheckGuardrailsResponse": "alias -> common.vault.detect.CheckGuardrailsResponse",
+ "skyflow.vault.detect.CustomType": "alias -> common.vault.detect.CustomType",
+ "skyflow.vault.detect.DeidentifyFileRequest": "alias -> common.vault.detect.DeidentifyFileRequest",
+ "skyflow.vault.detect.DeidentifyFileResponse": "alias -> common.vault.detect.DeidentifyFileResponse",
+ "skyflow.vault.detect.DeidentifyStringRequest": "alias -> common.vault.detect.DeidentifyStringRequest",
+ "skyflow.vault.detect.DeidentifyStringResponse": "alias -> common.vault.detect.DeidentifyStringResponse",
+ "skyflow.vault.detect.Detect": "alias -> common.vault.detect.Detect",
+ "skyflow.vault.detect.DetectConfiguration": "alias -> common.vault.detect.DetectConfiguration",
+ "skyflow.vault.detect.DetectController": "alias -> common.vault.detect.DetectController",
+ "skyflow.vault.detect.DetectedEntity": "alias -> common.vault.detect.DetectedEntity",
+ "skyflow.vault.detect.Document": "alias -> common.vault.detect.Document",
+ "skyflow.vault.detect.Entity": "alias -> common.vault.detect.Entity",
+ "skyflow.vault.detect.EntityLocation": "alias -> common.vault.detect.EntityLocation",
+ "skyflow.vault.detect.FileMapping": "alias -> common.vault.detect.FileMapping",
+ "skyflow.vault.detect.FileOutput": "alias -> common.vault.detect.FileOutput",
+ "skyflow.vault.detect.GetRunRequest": "alias -> common.vault.detect.GetRunRequest",
+ "skyflow.vault.detect.GetRunResponse": "alias -> common.vault.detect.GetRunResponse",
+ "skyflow.vault.detect.Image": "alias -> common.vault.detect.Image",
+ "skyflow.vault.detect.Media": "alias -> common.vault.detect.Media",
+ "skyflow.vault.detect.Metrics": "alias -> common.vault.detect.Metrics",
+ "skyflow.vault.detect.ObjectEntity": "alias -> common.vault.detect.ObjectEntity",
+ "skyflow.vault.detect.Pdf": "alias -> common.vault.detect.Pdf",
+ "skyflow.vault.detect.PollOptions": "alias -> common.vault.detect.PollOptions",
+ "skyflow.vault.detect.RedactionLevel": "class (RedactionRule)",
+ "skyflow.vault.detect.RedactionLevel.__init__": "def (self, entity_name: EntityType = None, redaction_type: RedactionType = None)",
+ "skyflow.vault.detect.RedactionLevel.entity_name": "attr",
+ "skyflow.vault.detect.RedactionLevel.redaction_type": "attr",
+ "skyflow.vault.detect.ReidentifyFileRequest": "alias -> common.vault.detect.ReidentifyFileRequest",
+ "skyflow.vault.detect.ReidentifyFileResponse": "alias -> common.vault.detect.ReidentifyFileResponse",
+ "skyflow.vault.detect.ReidentifyStringRequest": "alias -> common.vault.detect.ReidentifyStringRequest",
+ "skyflow.vault.detect.ReidentifyStringResponse": "alias -> common.vault.detect.ReidentifyStringResponse",
+ "skyflow.vault.detect.ShiftDates": "alias -> common.vault.detect.ShiftDates",
+ "skyflow.vault.detect.Transformation": "alias -> common.vault.detect.Transformation",
"skyflow.vault.tokens.DetokenizeRequest": "class ()",
"skyflow.vault.tokens.DetokenizeRequest.__init__": "def (self, data, continue_on_error = False)",
"skyflow.vault.tokens.DetokenizeRequest.continue_on_error": "attr",
diff --git a/skyvault/setup.py b/skyvault/setup.py
index 26fc8d05..81a2e3b5 100644
--- a/skyvault/setup.py
+++ b/skyvault/setup.py
@@ -7,6 +7,7 @@
from setuptools import setup, find_packages
from setuptools.command.build_py import build_py as _build_py
+from setuptools.command.sdist import sdist as _sdist
if sys.version_info < (3, 9):
@@ -15,13 +16,16 @@
HERE = os.path.abspath(os.path.dirname(__file__))
REPO_ROOT = os.path.dirname(HERE)
+VENDORED_COMMON = os.path.join(HERE, 'common')
COMMON_SRC = os.path.join(REPO_ROOT, 'common')
+if not os.path.isdir(COMMON_SRC):
+ COMMON_SRC = VENDORED_COMMON
with open(os.path.join(HERE, 'README.md'), 'r', encoding='utf-8') as f:
long_description = f.read()
# Anything under common/ that must never ride along into a built wheel.
-_COMMON_EXCLUDE_DIRS = {'__pycache__', '.pytest_cache', 'tests', '.mypy_cache'}
+_COMMON_EXCLUDE_DIRS = {'__pycache__', '.pytest_cache', 'tests', '.mypy_cache', 'build', 'dist'}
_COMMON_EXCLUDE_FILES = {'setup.py', 'pyproject.toml', 'requirements.txt', '.gitignore'}
_COMMON_EXCLUDE_SUFFIXES = ('.egg-info',)
@@ -37,8 +41,8 @@ def _ignore_common_files(_directory, names):
class CustomBuildPy(_build_py):
- """SK-2938 Option C: bundles the sibling common/ source tree into this variant's wheel
- (bdist_wheel/build --wheel only -- sdist doesn't invoke this and isn't supported here)."""
+ """Bundles the common/ source tree into this variant's wheel, from the sibling checkout or,
+ when building from an sdist, from the copy vendored into the tarball by CustomSdist."""
def run(self):
super().run()
@@ -48,18 +52,33 @@ def run(self):
shutil.copytree(COMMON_SRC, dest, ignore=_ignore_common_files)
+class CustomSdist(_sdist):
+ def run(self):
+ copied = False
+ if os.path.isdir(COMMON_SRC) and os.path.abspath(COMMON_SRC) != os.path.abspath(VENDORED_COMMON):
+ if os.path.exists(VENDORED_COMMON):
+ shutil.rmtree(VENDORED_COMMON)
+ shutil.copytree(COMMON_SRC, VENDORED_COMMON, ignore=_ignore_common_files)
+ copied = True
+ try:
+ super().run()
+ finally:
+ if copied:
+ shutil.rmtree(VENDORED_COMMON)
+
+
setup(
name='skyflow',
version=current_version,
author='Skyflow',
author_email='service-ops@skyflow.com',
- packages=find_packages(where='.', exclude=['test*', 'samples*']),
+ packages=find_packages(where='.', exclude=['test*', 'samples*', 'common', 'common.*']),
# Ship PEP 561 markers so type checkers (mypy/pyright) see the SDK's types.
package_data={
'skyflow': ['py.typed'],
'skyflow.generated.rest': ['py.typed'],
},
- cmdclass={'build_py': CustomBuildPy},
+ cmdclass={'build_py': CustomBuildPy, 'sdist': CustomSdist},
url='https://github.com/skyflowapi/skyflow-python/',
license='LICENSE',
description='Skyflow SDK for the Python programming language',
diff --git a/skyvault/skyflow/client/skyflow.py b/skyvault/skyflow/client/skyflow.py
index c464b2f7..1dc627b4 100644
--- a/skyvault/skyflow/client/skyflow.py
+++ b/skyvault/skyflow/client/skyflow.py
@@ -3,13 +3,14 @@
from skyflow.utils.logger import set_active_log_level
from skyflow.utils.validations import validate_connection_config, validate_update_connection_config
from skyflow.vault.client.client import VaultClient
-from skyflow.vault.controller import VaultController, Connection, Detect
+from skyflow.vault.controller import VaultController, Connection
+from skyflow.vault.detect import DetectController
Skyflow = make_skyflow_class(
vault_client_cls=VaultClient,
vault_controller_cls=VaultController,
connection_cls=Connection,
- detect_cls=Detect,
+ detect_cls=DetectController,
skyflow_messages=SkyflowMessages,
validate_connection_config=validate_connection_config,
validate_update_connection_config=validate_update_connection_config,
diff --git a/skyvault/skyflow/generated/rest/__init__.py b/skyvault/skyflow/generated/rest/__init__.py
index bdb94808..22cd6f9e 100644
--- a/skyvault/skyflow/generated/rest/__init__.py
+++ b/skyvault/skyflow/generated/rest/__init__.py
@@ -2,274 +2,165 @@
# isort: skip_file
-from .types import (
- AuditEventAuditResourceType,
- AuditEventContext,
- AuditEventData,
- AuditEventHttpInfo,
- BatchRecordMethod,
- ContextAccessType,
- ContextAuthMode,
- DeidentifiedFileOutput,
- DeidentifiedFileOutputProcessedFileExtension,
- DeidentifiedFileOutputProcessedFileType,
- DeidentifyFileResponse,
- DeidentifyStringResponse,
- DetectGuardrailsResponse,
- DetectGuardrailsResponseValidation,
- DetectRunsResponse,
- DetectRunsResponseOutputType,
- DetectRunsResponseStatus,
- DetokenizeRecordResponseValueType,
- ErrorResponse,
- ErrorResponseError,
- FileData,
- FileDataDataFormat,
- FileDataDeidentifyAudio,
- FileDataDeidentifyAudioDataFormat,
- FileDataDeidentifyDocument,
- FileDataDeidentifyDocumentDataFormat,
- FileDataDeidentifyImage,
- FileDataDeidentifyImageDataFormat,
- FileDataDeidentifyPdf,
- FileDataDeidentifyPresentation,
- FileDataDeidentifyPresentationDataFormat,
- FileDataDeidentifySpreadsheet,
- FileDataDeidentifySpreadsheetDataFormat,
- FileDataDeidentifyStructuredText,
- FileDataDeidentifyStructuredTextDataFormat,
- FileDataDeidentifyText,
- FileDataReidentifyFile,
- FileDataReidentifyFileDataFormat,
- Format,
- FormatMaskedItem,
- FormatPlaintextItem,
- FormatRedactedItem,
- GooglerpcStatus,
- HttpCode,
- IdentifyResponse,
- Locations,
- ProtobufAny,
- RedactionEnumRedaction,
- ReidentifiedFileOutput,
- ReidentifiedFileOutputProcessedFileExtension,
- ReidentifyFileResponse,
- ReidentifyFileResponseOutputType,
- ReidentifyFileResponseStatus,
- RequestActionType,
- ResourceId,
- ShiftDates,
- ShiftDatesEntityTypesItem,
- StringResponseEntities,
- TokenTypeMapping,
- TokenTypeMappingDefault,
- TokenTypeMappingEntityOnlyItem,
- TokenTypeMappingEntityUnqCounterItem,
- TokenTypeMappingVaultTokenItem,
- Transformations,
- UploadFileV2Response,
- Uuid,
- V1AuditAfterOptions,
- V1AuditEventResponse,
- V1AuditResponse,
- V1AuditResponseEvent,
- V1AuditResponseEventRequest,
- V1BatchOperationResponse,
- V1BatchRecord,
- V1BinListResponse,
- V1BulkDeleteRecordResponse,
- V1BulkGetRecordResponse,
- V1Byot,
- V1Card,
- V1DeleteFileResponse,
- V1DeleteRecordResponse,
- V1DetokenizeRecordRequest,
- V1DetokenizeRecordResponse,
- V1DetokenizeResponse,
- V1FieldRecords,
- V1FileAvScanStatus,
- V1GetAuthTokenResponse,
- V1GetFileScanStatusResponse,
- V1GetQueryResponse,
- V1InsertRecordResponse,
- V1MemberType,
- V1RecordMetaProperties,
- V1TokenizeRecordRequest,
- V1TokenizeRecordResponse,
- V1TokenizeResponse,
- V1UpdateRecordResponse,
- V1VaultFieldMapping,
- V1VaultSchemaConfig,
- WordCharacterCount,
-)
-from .errors import BadRequestError, InternalServerError, NotFoundError, UnauthorizedError
-from . import audit, authentication, bin_lookup, files, guardrails, query, records, strings, tokens
-from .audit import (
- AuditServiceListAuditEventsRequestFilterOpsActionType,
- AuditServiceListAuditEventsRequestFilterOpsContextAccessType,
- AuditServiceListAuditEventsRequestFilterOpsContextActorType,
- AuditServiceListAuditEventsRequestFilterOpsContextAuthMode,
- AuditServiceListAuditEventsRequestFilterOpsResourceType,
- AuditServiceListAuditEventsRequestSortOpsOrderBy,
-)
-from .client import AsyncSkyflow, Skyflow
-from .environment import SkyflowEnvironment
-from .files import (
- DeidentifyFileAudioRequestDeidentifyAudioEntityTypesItem,
- DeidentifyFileAudioRequestDeidentifyAudioOutputTranscription,
- DeidentifyFileDocumentPdfRequestDeidentifyPdfEntityTypesItem,
- DeidentifyFileImageRequestDeidentifyImageEntityTypesItem,
- DeidentifyFileImageRequestDeidentifyImageMaskingMethod,
- DeidentifyFileRequestDeidentifyDocumentEntityTypesItem,
- DeidentifyFileRequestDeidentifyPresentationEntityTypesItem,
- DeidentifyFileRequestDeidentifySpreadsheetEntityTypesItem,
- DeidentifyFileRequestDeidentifyStructuredTextEntityTypesItem,
- DeidentifyFileRequestDeidentifyTextEntityTypesItem,
- DeidentifyFileRequestEntityTypesItem,
-)
-from .records import (
- RecordServiceBulkGetRecordRequestOrderBy,
- RecordServiceBulkGetRecordRequestRedaction,
- RecordServiceGetRecordRequestRedaction,
-)
-from .strings import DeidentifyStringRequestEntityTypesItem
-from .version import __version__
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .types import (
+ BatchOperationResponse,
+ BatchRecord,
+ BatchRecordMethod,
+ BatchRecordRedaction,
+ BulkDeleteRecordResponse,
+ BulkGetRecordResponse,
+ DeleteRecordResponse,
+ DetokenizeRecordRequest,
+ DetokenizeRecordRequestRedaction,
+ DetokenizeRecordResponse,
+ DetokenizeRecordResponseValueType,
+ DetokenizeResponse,
+ ErrorResponse,
+ ErrorResponseError,
+ FieldRecords,
+ FileMetadata,
+ GetFieldRecords,
+ GetQueryResponse,
+ HttpCode,
+ InsertRecordResponse,
+ RecordMetaProperties,
+ TokenizeRecordRequest,
+ TokenizeRecordResponse,
+ TokenizeResponse,
+ UpdateRecordResponse,
+ UploadFileResponseV2,
+ )
+ from .errors import BadRequestError, InternalServerError, NotFoundError, UnauthorizedError
+ from . import files, query, records, tokens
+ from ._default_clients import DefaultAioHttpClient, DefaultAsyncHttpxClient
+ from .client import AsyncSkyflowAuth, SkyflowAuth
+ from .environment import SkyflowAuthEnvironment
+ from .records import (
+ GetRecordByIdRequestRedaction,
+ GetRecordsRequestOrderBy,
+ GetRecordsRequestRedaction,
+ InsertRecordRequestByot,
+ UpdateRecordRequestByot,
+ )
+ from .version import __version__
+_dynamic_imports: typing.Dict[str, str] = {
+ "AsyncSkyflowAuth": ".client",
+ "BadRequestError": ".errors",
+ "BatchOperationResponse": ".types",
+ "BatchRecord": ".types",
+ "BatchRecordMethod": ".types",
+ "BatchRecordRedaction": ".types",
+ "BulkDeleteRecordResponse": ".types",
+ "BulkGetRecordResponse": ".types",
+ "DefaultAioHttpClient": "._default_clients",
+ "DefaultAsyncHttpxClient": "._default_clients",
+ "DeleteRecordResponse": ".types",
+ "DetokenizeRecordRequest": ".types",
+ "DetokenizeRecordRequestRedaction": ".types",
+ "DetokenizeRecordResponse": ".types",
+ "DetokenizeRecordResponseValueType": ".types",
+ "DetokenizeResponse": ".types",
+ "ErrorResponse": ".types",
+ "ErrorResponseError": ".types",
+ "FieldRecords": ".types",
+ "FileMetadata": ".types",
+ "GetFieldRecords": ".types",
+ "GetQueryResponse": ".types",
+ "GetRecordByIdRequestRedaction": ".records",
+ "GetRecordsRequestOrderBy": ".records",
+ "GetRecordsRequestRedaction": ".records",
+ "HttpCode": ".types",
+ "InsertRecordRequestByot": ".records",
+ "InsertRecordResponse": ".types",
+ "InternalServerError": ".errors",
+ "NotFoundError": ".errors",
+ "RecordMetaProperties": ".types",
+ "SkyflowAuth": ".client",
+ "SkyflowAuthEnvironment": ".environment",
+ "TokenizeRecordRequest": ".types",
+ "TokenizeRecordResponse": ".types",
+ "TokenizeResponse": ".types",
+ "UnauthorizedError": ".errors",
+ "UpdateRecordRequestByot": ".records",
+ "UpdateRecordResponse": ".types",
+ "UploadFileResponseV2": ".types",
+ "__version__": ".version",
+ "files": ".files",
+ "query": ".query",
+ "records": ".records",
+ "tokens": ".tokens",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
__all__ = [
- "AsyncSkyflow",
- "AuditEventAuditResourceType",
- "AuditEventContext",
- "AuditEventData",
- "AuditEventHttpInfo",
- "AuditServiceListAuditEventsRequestFilterOpsActionType",
- "AuditServiceListAuditEventsRequestFilterOpsContextAccessType",
- "AuditServiceListAuditEventsRequestFilterOpsContextActorType",
- "AuditServiceListAuditEventsRequestFilterOpsContextAuthMode",
- "AuditServiceListAuditEventsRequestFilterOpsResourceType",
- "AuditServiceListAuditEventsRequestSortOpsOrderBy",
+ "AsyncSkyflowAuth",
"BadRequestError",
+ "BatchOperationResponse",
+ "BatchRecord",
"BatchRecordMethod",
- "ContextAccessType",
- "ContextAuthMode",
- "DeidentifiedFileOutput",
- "DeidentifiedFileOutputProcessedFileExtension",
- "DeidentifiedFileOutputProcessedFileType",
- "DeidentifyFileAudioRequestDeidentifyAudioEntityTypesItem",
- "DeidentifyFileAudioRequestDeidentifyAudioOutputTranscription",
- "DeidentifyFileDocumentPdfRequestDeidentifyPdfEntityTypesItem",
- "DeidentifyFileImageRequestDeidentifyImageEntityTypesItem",
- "DeidentifyFileImageRequestDeidentifyImageMaskingMethod",
- "DeidentifyFileRequestDeidentifyDocumentEntityTypesItem",
- "DeidentifyFileRequestDeidentifyPresentationEntityTypesItem",
- "DeidentifyFileRequestDeidentifySpreadsheetEntityTypesItem",
- "DeidentifyFileRequestDeidentifyStructuredTextEntityTypesItem",
- "DeidentifyFileRequestDeidentifyTextEntityTypesItem",
- "DeidentifyFileRequestEntityTypesItem",
- "DeidentifyFileResponse",
- "DeidentifyStringRequestEntityTypesItem",
- "DeidentifyStringResponse",
- "DetectGuardrailsResponse",
- "DetectGuardrailsResponseValidation",
- "DetectRunsResponse",
- "DetectRunsResponseOutputType",
- "DetectRunsResponseStatus",
+ "BatchRecordRedaction",
+ "BulkDeleteRecordResponse",
+ "BulkGetRecordResponse",
+ "DefaultAioHttpClient",
+ "DefaultAsyncHttpxClient",
+ "DeleteRecordResponse",
+ "DetokenizeRecordRequest",
+ "DetokenizeRecordRequestRedaction",
+ "DetokenizeRecordResponse",
"DetokenizeRecordResponseValueType",
+ "DetokenizeResponse",
"ErrorResponse",
"ErrorResponseError",
- "FileData",
- "FileDataDataFormat",
- "FileDataDeidentifyAudio",
- "FileDataDeidentifyAudioDataFormat",
- "FileDataDeidentifyDocument",
- "FileDataDeidentifyDocumentDataFormat",
- "FileDataDeidentifyImage",
- "FileDataDeidentifyImageDataFormat",
- "FileDataDeidentifyPdf",
- "FileDataDeidentifyPresentation",
- "FileDataDeidentifyPresentationDataFormat",
- "FileDataDeidentifySpreadsheet",
- "FileDataDeidentifySpreadsheetDataFormat",
- "FileDataDeidentifyStructuredText",
- "FileDataDeidentifyStructuredTextDataFormat",
- "FileDataDeidentifyText",
- "FileDataReidentifyFile",
- "FileDataReidentifyFileDataFormat",
- "Format",
- "FormatMaskedItem",
- "FormatPlaintextItem",
- "FormatRedactedItem",
- "GooglerpcStatus",
+ "FieldRecords",
+ "FileMetadata",
+ "GetFieldRecords",
+ "GetQueryResponse",
+ "GetRecordByIdRequestRedaction",
+ "GetRecordsRequestOrderBy",
+ "GetRecordsRequestRedaction",
"HttpCode",
- "IdentifyResponse",
+ "InsertRecordRequestByot",
+ "InsertRecordResponse",
"InternalServerError",
- "Locations",
"NotFoundError",
- "ProtobufAny",
- "RecordServiceBulkGetRecordRequestOrderBy",
- "RecordServiceBulkGetRecordRequestRedaction",
- "RecordServiceGetRecordRequestRedaction",
- "RedactionEnumRedaction",
- "ReidentifiedFileOutput",
- "ReidentifiedFileOutputProcessedFileExtension",
- "ReidentifyFileResponse",
- "ReidentifyFileResponseOutputType",
- "ReidentifyFileResponseStatus",
- "RequestActionType",
- "ResourceId",
- "ShiftDates",
- "ShiftDatesEntityTypesItem",
- "Skyflow",
- "SkyflowEnvironment",
- "StringResponseEntities",
- "TokenTypeMapping",
- "TokenTypeMappingDefault",
- "TokenTypeMappingEntityOnlyItem",
- "TokenTypeMappingEntityUnqCounterItem",
- "TokenTypeMappingVaultTokenItem",
- "Transformations",
+ "RecordMetaProperties",
+ "SkyflowAuth",
+ "SkyflowAuthEnvironment",
+ "TokenizeRecordRequest",
+ "TokenizeRecordResponse",
+ "TokenizeResponse",
"UnauthorizedError",
- "UploadFileV2Response",
- "Uuid",
- "V1AuditAfterOptions",
- "V1AuditEventResponse",
- "V1AuditResponse",
- "V1AuditResponseEvent",
- "V1AuditResponseEventRequest",
- "V1BatchOperationResponse",
- "V1BatchRecord",
- "V1BinListResponse",
- "V1BulkDeleteRecordResponse",
- "V1BulkGetRecordResponse",
- "V1Byot",
- "V1Card",
- "V1DeleteFileResponse",
- "V1DeleteRecordResponse",
- "V1DetokenizeRecordRequest",
- "V1DetokenizeRecordResponse",
- "V1DetokenizeResponse",
- "V1FieldRecords",
- "V1FileAvScanStatus",
- "V1GetAuthTokenResponse",
- "V1GetFileScanStatusResponse",
- "V1GetQueryResponse",
- "V1InsertRecordResponse",
- "V1MemberType",
- "V1RecordMetaProperties",
- "V1TokenizeRecordRequest",
- "V1TokenizeRecordResponse",
- "V1TokenizeResponse",
- "V1UpdateRecordResponse",
- "V1VaultFieldMapping",
- "V1VaultSchemaConfig",
- "WordCharacterCount",
+ "UpdateRecordRequestByot",
+ "UpdateRecordResponse",
+ "UploadFileResponseV2",
"__version__",
- "audit",
- "authentication",
- "bin_lookup",
"files",
- "guardrails",
"query",
"records",
- "strings",
"tokens",
]
diff --git a/skyvault/skyflow/generated/rest/_default_clients.py b/skyvault/skyflow/generated/rest/_default_clients.py
new file mode 100644
index 00000000..057d547f
--- /dev/null
+++ b/skyvault/skyflow/generated/rest/_default_clients.py
@@ -0,0 +1,32 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import httpx
+
+SDK_DEFAULT_TIMEOUT = 60
+
+try:
+ import httpx_aiohttp # type: ignore[import-not-found]
+except ImportError:
+
+ class DefaultAioHttpClient(httpx.AsyncClient): # type: ignore
+ def __init__(self, **kwargs: typing.Any) -> None:
+ raise RuntimeError(
+ "To use the aiohttp client, install the aiohttp extra: pip install skyflow.generated.rest[aiohttp]"
+ )
+
+else:
+
+ class DefaultAioHttpClient(httpx_aiohttp.HttpxAiohttpClient): # type: ignore
+ def __init__(self, **kwargs: typing.Any) -> None:
+ kwargs.setdefault("timeout", SDK_DEFAULT_TIMEOUT)
+ kwargs.setdefault("follow_redirects", True)
+ super().__init__(**kwargs)
+
+
+class DefaultAsyncHttpxClient(httpx.AsyncClient):
+ def __init__(self, **kwargs: typing.Any) -> None:
+ kwargs.setdefault("timeout", SDK_DEFAULT_TIMEOUT)
+ kwargs.setdefault("follow_redirects", True)
+ super().__init__(**kwargs)
diff --git a/skyvault/skyflow/generated/rest/audit/__init__.py b/skyvault/skyflow/generated/rest/audit/__init__.py
deleted file mode 100644
index e3b20ff0..00000000
--- a/skyvault/skyflow/generated/rest/audit/__init__.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-# isort: skip_file
-
-from .types import (
- AuditServiceListAuditEventsRequestFilterOpsActionType,
- AuditServiceListAuditEventsRequestFilterOpsContextAccessType,
- AuditServiceListAuditEventsRequestFilterOpsContextActorType,
- AuditServiceListAuditEventsRequestFilterOpsContextAuthMode,
- AuditServiceListAuditEventsRequestFilterOpsResourceType,
- AuditServiceListAuditEventsRequestSortOpsOrderBy,
-)
-
-__all__ = [
- "AuditServiceListAuditEventsRequestFilterOpsActionType",
- "AuditServiceListAuditEventsRequestFilterOpsContextAccessType",
- "AuditServiceListAuditEventsRequestFilterOpsContextActorType",
- "AuditServiceListAuditEventsRequestFilterOpsContextAuthMode",
- "AuditServiceListAuditEventsRequestFilterOpsResourceType",
- "AuditServiceListAuditEventsRequestSortOpsOrderBy",
-]
diff --git a/skyvault/skyflow/generated/rest/audit/client.py b/skyvault/skyflow/generated/rest/audit/client.py
deleted file mode 100644
index 6f1d1039..00000000
--- a/skyvault/skyflow/generated/rest/audit/client.py
+++ /dev/null
@@ -1,540 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
-from ..core.request_options import RequestOptions
-from ..types.v_1_audit_response import V1AuditResponse
-from .raw_client import AsyncRawAuditClient, RawAuditClient
-from .types.audit_service_list_audit_events_request_filter_ops_action_type import (
- AuditServiceListAuditEventsRequestFilterOpsActionType,
-)
-from .types.audit_service_list_audit_events_request_filter_ops_context_access_type import (
- AuditServiceListAuditEventsRequestFilterOpsContextAccessType,
-)
-from .types.audit_service_list_audit_events_request_filter_ops_context_actor_type import (
- AuditServiceListAuditEventsRequestFilterOpsContextActorType,
-)
-from .types.audit_service_list_audit_events_request_filter_ops_context_auth_mode import (
- AuditServiceListAuditEventsRequestFilterOpsContextAuthMode,
-)
-from .types.audit_service_list_audit_events_request_filter_ops_resource_type import (
- AuditServiceListAuditEventsRequestFilterOpsResourceType,
-)
-from .types.audit_service_list_audit_events_request_sort_ops_order_by import (
- AuditServiceListAuditEventsRequestSortOpsOrderBy,
-)
-
-
-class AuditClient:
- def __init__(self, *, client_wrapper: SyncClientWrapper):
- self._raw_client = RawAuditClient(client_wrapper=client_wrapper)
-
- @property
- def with_raw_response(self) -> RawAuditClient:
- """
- Retrieves a raw implementation of this client that returns raw responses.
-
- Returns
- -------
- RawAuditClient
- """
- return self._raw_client
-
- def audit_service_list_audit_events(
- self,
- *,
- filter_ops_account_id: str,
- filter_ops_context_change_id: typing.Optional[str] = None,
- filter_ops_context_request_id: typing.Optional[str] = None,
- filter_ops_context_trace_id: typing.Optional[str] = None,
- filter_ops_context_session_id: typing.Optional[str] = None,
- filter_ops_context_actor: typing.Optional[str] = None,
- filter_ops_context_actor_type: typing.Optional[
- AuditServiceListAuditEventsRequestFilterOpsContextActorType
- ] = None,
- filter_ops_context_access_type: typing.Optional[
- AuditServiceListAuditEventsRequestFilterOpsContextAccessType
- ] = None,
- filter_ops_context_ip_address: typing.Optional[str] = None,
- filter_ops_context_origin: typing.Optional[str] = None,
- filter_ops_context_auth_mode: typing.Optional[
- AuditServiceListAuditEventsRequestFilterOpsContextAuthMode
- ] = None,
- filter_ops_context_jwt_id: typing.Optional[str] = None,
- filter_ops_context_bearer_token_context_id: typing.Optional[str] = None,
- filter_ops_parent_account_id: typing.Optional[str] = None,
- filter_ops_workspace_id: typing.Optional[str] = None,
- filter_ops_vault_id: typing.Optional[str] = None,
- filter_ops_resource_i_ds: typing.Optional[str] = None,
- filter_ops_action_type: typing.Optional[AuditServiceListAuditEventsRequestFilterOpsActionType] = None,
- filter_ops_resource_type: typing.Optional[AuditServiceListAuditEventsRequestFilterOpsResourceType] = None,
- filter_ops_tags: typing.Optional[str] = None,
- filter_ops_response_code: typing.Optional[int] = None,
- filter_ops_start_time: typing.Optional[str] = None,
- filter_ops_end_time: typing.Optional[str] = None,
- filter_ops_api_name: typing.Optional[str] = None,
- filter_ops_response_message: typing.Optional[str] = None,
- filter_ops_http_method: typing.Optional[str] = None,
- filter_ops_http_uri: typing.Optional[str] = None,
- sort_ops_sort_by: typing.Optional[str] = None,
- sort_ops_order_by: typing.Optional[AuditServiceListAuditEventsRequestSortOpsOrderBy] = None,
- after_ops_timestamp: typing.Optional[str] = None,
- after_ops_change_id: typing.Optional[str] = None,
- limit: typing.Optional[int] = None,
- offset: typing.Optional[int] = None,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> V1AuditResponse:
- """
- Lists audit events that match query parameters.
-
- Parameters
- ----------
- filter_ops_account_id : str
- Resources with the specified account ID.
-
- filter_ops_context_change_id : typing.Optional[str]
- ID for the audit event.
-
- filter_ops_context_request_id : typing.Optional[str]
- ID for the request that caused the event.
-
- filter_ops_context_trace_id : typing.Optional[str]
- ID for the request set by the service that received the request.
-
- filter_ops_context_session_id : typing.Optional[str]
- ID for the session in which the request was sent.
-
- filter_ops_context_actor : typing.Optional[str]
- Member who sent the request. Depending on `actorType`, this may be a user ID or a service account ID.
-
- filter_ops_context_actor_type : typing.Optional[AuditServiceListAuditEventsRequestFilterOpsContextActorType]
- Type of member who sent the request.
-
- filter_ops_context_access_type : typing.Optional[AuditServiceListAuditEventsRequestFilterOpsContextAccessType]
- Type of access for the request.
-
- filter_ops_context_ip_address : typing.Optional[str]
- IP Address of the client that made the request.
-
- filter_ops_context_origin : typing.Optional[str]
- HTTP Origin request header (including scheme, hostname, and port) of the request.
-
- filter_ops_context_auth_mode : typing.Optional[AuditServiceListAuditEventsRequestFilterOpsContextAuthMode]
- Authentication mode the `actor` used.
-
- filter_ops_context_jwt_id : typing.Optional[str]
- ID of the JWT token.
-
- filter_ops_context_bearer_token_context_id : typing.Optional[str]
- Embedded User Context.
-
- filter_ops_parent_account_id : typing.Optional[str]
- Resources with the specified parent account ID.
-
- filter_ops_workspace_id : typing.Optional[str]
- Resources with the specified workspace ID.
-
- filter_ops_vault_id : typing.Optional[str]
- Resources with the specified vault ID.
-
- filter_ops_resource_i_ds : typing.Optional[str]
- Resources with a specified ID. If a resource matches at least one ID, the associated event is returned. Format is a comma-separated list of "\/\". For example, "VAULT/12345, USER/67890".
-
- filter_ops_action_type : typing.Optional[AuditServiceListAuditEventsRequestFilterOpsActionType]
- Events with the specified action type.
-
- filter_ops_resource_type : typing.Optional[AuditServiceListAuditEventsRequestFilterOpsResourceType]
- Resources with the specified type.
-
- filter_ops_tags : typing.Optional[str]
- Events with associated tags. If an event matches at least one tag, the event is returned. Comma-separated list. For example, "login, get".
-
- filter_ops_response_code : typing.Optional[int]
- HTTP response code of the request.
-
- filter_ops_start_time : typing.Optional[str]
- Start timestamp for the query, in SQL format.
-
- filter_ops_end_time : typing.Optional[str]
- End timestamp for the query, in SQL format.
-
- filter_ops_api_name : typing.Optional[str]
- Name of the API called in the request.
-
- filter_ops_response_message : typing.Optional[str]
- Response message of the request.
-
- filter_ops_http_method : typing.Optional[str]
- HTTP method of the request.
-
- filter_ops_http_uri : typing.Optional[str]
- HTTP URI of the request.
-
- sort_ops_sort_by : typing.Optional[str]
- Fully-qualified field by which to sort results. Field names should be in camel case (for example, "capitalization.camelCase").
-
- sort_ops_order_by : typing.Optional[AuditServiceListAuditEventsRequestSortOpsOrderBy]
- Ascending or descending ordering of results.
-
- after_ops_timestamp : typing.Optional[str]
- Timestamp provided in the previous audit response's `nextOps` attribute. An alternate way to manage response pagination. Can't be used with `sortOps` or `offset`. For the first request in a series of audit requests, leave blank.
-
- after_ops_change_id : typing.Optional[str]
- Change ID provided in the previous audit response's `nextOps` attribute. An alternate way to manage response pagination. Can't be used with `sortOps` or `offset`. For the first request in a series of audit requests, leave blank.
-
- limit : typing.Optional[int]
- Number of results to return.
-
- offset : typing.Optional[int]
- Record position at which to start returning results.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- V1AuditResponse
- A successful response.
-
- Examples
- --------
- from skyflow import Skyflow
-
- client = Skyflow(
- token="YOUR_TOKEN",
- )
- client.audit.audit_service_list_audit_events(
- filter_ops_context_change_id="filterOps.context.changeID",
- filter_ops_context_request_id="filterOps.context.requestID",
- filter_ops_context_trace_id="filterOps.context.traceID",
- filter_ops_context_session_id="filterOps.context.sessionID",
- filter_ops_context_actor="filterOps.context.actor",
- filter_ops_context_actor_type="NONE",
- filter_ops_context_access_type="ACCESS_NONE",
- filter_ops_context_ip_address="filterOps.context.ipAddress",
- filter_ops_context_origin="filterOps.context.origin",
- filter_ops_context_auth_mode="AUTH_NONE",
- filter_ops_context_jwt_id="filterOps.context.jwtID",
- filter_ops_context_bearer_token_context_id="filterOps.context.bearerTokenContextID",
- filter_ops_parent_account_id="filterOps.parentAccountID",
- filter_ops_account_id="filterOps.accountID",
- filter_ops_workspace_id="filterOps.workspaceID",
- filter_ops_vault_id="filterOps.vaultID",
- filter_ops_resource_i_ds="filterOps.resourceIDs",
- filter_ops_action_type="NONE",
- filter_ops_resource_type="NONE_API",
- filter_ops_tags="filterOps.tags",
- filter_ops_response_code=1,
- filter_ops_start_time="filterOps.startTime",
- filter_ops_end_time="filterOps.endTime",
- filter_ops_api_name="filterOps.apiName",
- filter_ops_response_message="filterOps.responseMessage",
- filter_ops_http_method="filterOps.httpMethod",
- filter_ops_http_uri="filterOps.httpURI",
- sort_ops_sort_by="sortOps.sortBy",
- sort_ops_order_by="ASCENDING",
- after_ops_timestamp="afterOps.timestamp",
- after_ops_change_id="afterOps.changeID",
- limit=1000000,
- offset=1000000,
- )
- """
- _response = self._raw_client.audit_service_list_audit_events(
- filter_ops_account_id=filter_ops_account_id,
- filter_ops_context_change_id=filter_ops_context_change_id,
- filter_ops_context_request_id=filter_ops_context_request_id,
- filter_ops_context_trace_id=filter_ops_context_trace_id,
- filter_ops_context_session_id=filter_ops_context_session_id,
- filter_ops_context_actor=filter_ops_context_actor,
- filter_ops_context_actor_type=filter_ops_context_actor_type,
- filter_ops_context_access_type=filter_ops_context_access_type,
- filter_ops_context_ip_address=filter_ops_context_ip_address,
- filter_ops_context_origin=filter_ops_context_origin,
- filter_ops_context_auth_mode=filter_ops_context_auth_mode,
- filter_ops_context_jwt_id=filter_ops_context_jwt_id,
- filter_ops_context_bearer_token_context_id=filter_ops_context_bearer_token_context_id,
- filter_ops_parent_account_id=filter_ops_parent_account_id,
- filter_ops_workspace_id=filter_ops_workspace_id,
- filter_ops_vault_id=filter_ops_vault_id,
- filter_ops_resource_i_ds=filter_ops_resource_i_ds,
- filter_ops_action_type=filter_ops_action_type,
- filter_ops_resource_type=filter_ops_resource_type,
- filter_ops_tags=filter_ops_tags,
- filter_ops_response_code=filter_ops_response_code,
- filter_ops_start_time=filter_ops_start_time,
- filter_ops_end_time=filter_ops_end_time,
- filter_ops_api_name=filter_ops_api_name,
- filter_ops_response_message=filter_ops_response_message,
- filter_ops_http_method=filter_ops_http_method,
- filter_ops_http_uri=filter_ops_http_uri,
- sort_ops_sort_by=sort_ops_sort_by,
- sort_ops_order_by=sort_ops_order_by,
- after_ops_timestamp=after_ops_timestamp,
- after_ops_change_id=after_ops_change_id,
- limit=limit,
- offset=offset,
- request_options=request_options,
- )
- return _response.data
-
-
-class AsyncAuditClient:
- def __init__(self, *, client_wrapper: AsyncClientWrapper):
- self._raw_client = AsyncRawAuditClient(client_wrapper=client_wrapper)
-
- @property
- def with_raw_response(self) -> AsyncRawAuditClient:
- """
- Retrieves a raw implementation of this client that returns raw responses.
-
- Returns
- -------
- AsyncRawAuditClient
- """
- return self._raw_client
-
- async def audit_service_list_audit_events(
- self,
- *,
- filter_ops_account_id: str,
- filter_ops_context_change_id: typing.Optional[str] = None,
- filter_ops_context_request_id: typing.Optional[str] = None,
- filter_ops_context_trace_id: typing.Optional[str] = None,
- filter_ops_context_session_id: typing.Optional[str] = None,
- filter_ops_context_actor: typing.Optional[str] = None,
- filter_ops_context_actor_type: typing.Optional[
- AuditServiceListAuditEventsRequestFilterOpsContextActorType
- ] = None,
- filter_ops_context_access_type: typing.Optional[
- AuditServiceListAuditEventsRequestFilterOpsContextAccessType
- ] = None,
- filter_ops_context_ip_address: typing.Optional[str] = None,
- filter_ops_context_origin: typing.Optional[str] = None,
- filter_ops_context_auth_mode: typing.Optional[
- AuditServiceListAuditEventsRequestFilterOpsContextAuthMode
- ] = None,
- filter_ops_context_jwt_id: typing.Optional[str] = None,
- filter_ops_context_bearer_token_context_id: typing.Optional[str] = None,
- filter_ops_parent_account_id: typing.Optional[str] = None,
- filter_ops_workspace_id: typing.Optional[str] = None,
- filter_ops_vault_id: typing.Optional[str] = None,
- filter_ops_resource_i_ds: typing.Optional[str] = None,
- filter_ops_action_type: typing.Optional[AuditServiceListAuditEventsRequestFilterOpsActionType] = None,
- filter_ops_resource_type: typing.Optional[AuditServiceListAuditEventsRequestFilterOpsResourceType] = None,
- filter_ops_tags: typing.Optional[str] = None,
- filter_ops_response_code: typing.Optional[int] = None,
- filter_ops_start_time: typing.Optional[str] = None,
- filter_ops_end_time: typing.Optional[str] = None,
- filter_ops_api_name: typing.Optional[str] = None,
- filter_ops_response_message: typing.Optional[str] = None,
- filter_ops_http_method: typing.Optional[str] = None,
- filter_ops_http_uri: typing.Optional[str] = None,
- sort_ops_sort_by: typing.Optional[str] = None,
- sort_ops_order_by: typing.Optional[AuditServiceListAuditEventsRequestSortOpsOrderBy] = None,
- after_ops_timestamp: typing.Optional[str] = None,
- after_ops_change_id: typing.Optional[str] = None,
- limit: typing.Optional[int] = None,
- offset: typing.Optional[int] = None,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> V1AuditResponse:
- """
- Lists audit events that match query parameters.
-
- Parameters
- ----------
- filter_ops_account_id : str
- Resources with the specified account ID.
-
- filter_ops_context_change_id : typing.Optional[str]
- ID for the audit event.
-
- filter_ops_context_request_id : typing.Optional[str]
- ID for the request that caused the event.
-
- filter_ops_context_trace_id : typing.Optional[str]
- ID for the request set by the service that received the request.
-
- filter_ops_context_session_id : typing.Optional[str]
- ID for the session in which the request was sent.
-
- filter_ops_context_actor : typing.Optional[str]
- Member who sent the request. Depending on `actorType`, this may be a user ID or a service account ID.
-
- filter_ops_context_actor_type : typing.Optional[AuditServiceListAuditEventsRequestFilterOpsContextActorType]
- Type of member who sent the request.
-
- filter_ops_context_access_type : typing.Optional[AuditServiceListAuditEventsRequestFilterOpsContextAccessType]
- Type of access for the request.
-
- filter_ops_context_ip_address : typing.Optional[str]
- IP Address of the client that made the request.
-
- filter_ops_context_origin : typing.Optional[str]
- HTTP Origin request header (including scheme, hostname, and port) of the request.
-
- filter_ops_context_auth_mode : typing.Optional[AuditServiceListAuditEventsRequestFilterOpsContextAuthMode]
- Authentication mode the `actor` used.
-
- filter_ops_context_jwt_id : typing.Optional[str]
- ID of the JWT token.
-
- filter_ops_context_bearer_token_context_id : typing.Optional[str]
- Embedded User Context.
-
- filter_ops_parent_account_id : typing.Optional[str]
- Resources with the specified parent account ID.
-
- filter_ops_workspace_id : typing.Optional[str]
- Resources with the specified workspace ID.
-
- filter_ops_vault_id : typing.Optional[str]
- Resources with the specified vault ID.
-
- filter_ops_resource_i_ds : typing.Optional[str]
- Resources with a specified ID. If a resource matches at least one ID, the associated event is returned. Format is a comma-separated list of "\/\". For example, "VAULT/12345, USER/67890".
-
- filter_ops_action_type : typing.Optional[AuditServiceListAuditEventsRequestFilterOpsActionType]
- Events with the specified action type.
-
- filter_ops_resource_type : typing.Optional[AuditServiceListAuditEventsRequestFilterOpsResourceType]
- Resources with the specified type.
-
- filter_ops_tags : typing.Optional[str]
- Events with associated tags. If an event matches at least one tag, the event is returned. Comma-separated list. For example, "login, get".
-
- filter_ops_response_code : typing.Optional[int]
- HTTP response code of the request.
-
- filter_ops_start_time : typing.Optional[str]
- Start timestamp for the query, in SQL format.
-
- filter_ops_end_time : typing.Optional[str]
- End timestamp for the query, in SQL format.
-
- filter_ops_api_name : typing.Optional[str]
- Name of the API called in the request.
-
- filter_ops_response_message : typing.Optional[str]
- Response message of the request.
-
- filter_ops_http_method : typing.Optional[str]
- HTTP method of the request.
-
- filter_ops_http_uri : typing.Optional[str]
- HTTP URI of the request.
-
- sort_ops_sort_by : typing.Optional[str]
- Fully-qualified field by which to sort results. Field names should be in camel case (for example, "capitalization.camelCase").
-
- sort_ops_order_by : typing.Optional[AuditServiceListAuditEventsRequestSortOpsOrderBy]
- Ascending or descending ordering of results.
-
- after_ops_timestamp : typing.Optional[str]
- Timestamp provided in the previous audit response's `nextOps` attribute. An alternate way to manage response pagination. Can't be used with `sortOps` or `offset`. For the first request in a series of audit requests, leave blank.
-
- after_ops_change_id : typing.Optional[str]
- Change ID provided in the previous audit response's `nextOps` attribute. An alternate way to manage response pagination. Can't be used with `sortOps` or `offset`. For the first request in a series of audit requests, leave blank.
-
- limit : typing.Optional[int]
- Number of results to return.
-
- offset : typing.Optional[int]
- Record position at which to start returning results.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- V1AuditResponse
- A successful response.
-
- Examples
- --------
- import asyncio
-
- from skyflow import AsyncSkyflow
-
- client = AsyncSkyflow(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.audit.audit_service_list_audit_events(
- filter_ops_context_change_id="filterOps.context.changeID",
- filter_ops_context_request_id="filterOps.context.requestID",
- filter_ops_context_trace_id="filterOps.context.traceID",
- filter_ops_context_session_id="filterOps.context.sessionID",
- filter_ops_context_actor="filterOps.context.actor",
- filter_ops_context_actor_type="NONE",
- filter_ops_context_access_type="ACCESS_NONE",
- filter_ops_context_ip_address="filterOps.context.ipAddress",
- filter_ops_context_origin="filterOps.context.origin",
- filter_ops_context_auth_mode="AUTH_NONE",
- filter_ops_context_jwt_id="filterOps.context.jwtID",
- filter_ops_context_bearer_token_context_id="filterOps.context.bearerTokenContextID",
- filter_ops_parent_account_id="filterOps.parentAccountID",
- filter_ops_account_id="filterOps.accountID",
- filter_ops_workspace_id="filterOps.workspaceID",
- filter_ops_vault_id="filterOps.vaultID",
- filter_ops_resource_i_ds="filterOps.resourceIDs",
- filter_ops_action_type="NONE",
- filter_ops_resource_type="NONE_API",
- filter_ops_tags="filterOps.tags",
- filter_ops_response_code=1,
- filter_ops_start_time="filterOps.startTime",
- filter_ops_end_time="filterOps.endTime",
- filter_ops_api_name="filterOps.apiName",
- filter_ops_response_message="filterOps.responseMessage",
- filter_ops_http_method="filterOps.httpMethod",
- filter_ops_http_uri="filterOps.httpURI",
- sort_ops_sort_by="sortOps.sortBy",
- sort_ops_order_by="ASCENDING",
- after_ops_timestamp="afterOps.timestamp",
- after_ops_change_id="afterOps.changeID",
- limit=1000000,
- offset=1000000,
- )
-
-
- asyncio.run(main())
- """
- _response = await self._raw_client.audit_service_list_audit_events(
- filter_ops_account_id=filter_ops_account_id,
- filter_ops_context_change_id=filter_ops_context_change_id,
- filter_ops_context_request_id=filter_ops_context_request_id,
- filter_ops_context_trace_id=filter_ops_context_trace_id,
- filter_ops_context_session_id=filter_ops_context_session_id,
- filter_ops_context_actor=filter_ops_context_actor,
- filter_ops_context_actor_type=filter_ops_context_actor_type,
- filter_ops_context_access_type=filter_ops_context_access_type,
- filter_ops_context_ip_address=filter_ops_context_ip_address,
- filter_ops_context_origin=filter_ops_context_origin,
- filter_ops_context_auth_mode=filter_ops_context_auth_mode,
- filter_ops_context_jwt_id=filter_ops_context_jwt_id,
- filter_ops_context_bearer_token_context_id=filter_ops_context_bearer_token_context_id,
- filter_ops_parent_account_id=filter_ops_parent_account_id,
- filter_ops_workspace_id=filter_ops_workspace_id,
- filter_ops_vault_id=filter_ops_vault_id,
- filter_ops_resource_i_ds=filter_ops_resource_i_ds,
- filter_ops_action_type=filter_ops_action_type,
- filter_ops_resource_type=filter_ops_resource_type,
- filter_ops_tags=filter_ops_tags,
- filter_ops_response_code=filter_ops_response_code,
- filter_ops_start_time=filter_ops_start_time,
- filter_ops_end_time=filter_ops_end_time,
- filter_ops_api_name=filter_ops_api_name,
- filter_ops_response_message=filter_ops_response_message,
- filter_ops_http_method=filter_ops_http_method,
- filter_ops_http_uri=filter_ops_http_uri,
- sort_ops_sort_by=sort_ops_sort_by,
- sort_ops_order_by=sort_ops_order_by,
- after_ops_timestamp=after_ops_timestamp,
- after_ops_change_id=after_ops_change_id,
- limit=limit,
- offset=offset,
- request_options=request_options,
- )
- return _response.data
diff --git a/skyvault/skyflow/generated/rest/audit/raw_client.py b/skyvault/skyflow/generated/rest/audit/raw_client.py
deleted file mode 100644
index 3d1277bf..00000000
--- a/skyvault/skyflow/generated/rest/audit/raw_client.py
+++ /dev/null
@@ -1,484 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-from json.decoder import JSONDecodeError
-
-from ..core.api_error import ApiError
-from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
-from ..core.http_response import AsyncHttpResponse, HttpResponse
-from ..core.pydantic_utilities import parse_obj_as
-from ..core.request_options import RequestOptions
-from ..errors.not_found_error import NotFoundError
-from ..types.v_1_audit_response import V1AuditResponse
-from .types.audit_service_list_audit_events_request_filter_ops_action_type import (
- AuditServiceListAuditEventsRequestFilterOpsActionType,
-)
-from .types.audit_service_list_audit_events_request_filter_ops_context_access_type import (
- AuditServiceListAuditEventsRequestFilterOpsContextAccessType,
-)
-from .types.audit_service_list_audit_events_request_filter_ops_context_actor_type import (
- AuditServiceListAuditEventsRequestFilterOpsContextActorType,
-)
-from .types.audit_service_list_audit_events_request_filter_ops_context_auth_mode import (
- AuditServiceListAuditEventsRequestFilterOpsContextAuthMode,
-)
-from .types.audit_service_list_audit_events_request_filter_ops_resource_type import (
- AuditServiceListAuditEventsRequestFilterOpsResourceType,
-)
-from .types.audit_service_list_audit_events_request_sort_ops_order_by import (
- AuditServiceListAuditEventsRequestSortOpsOrderBy,
-)
-
-
-class RawAuditClient:
- def __init__(self, *, client_wrapper: SyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- def audit_service_list_audit_events(
- self,
- *,
- filter_ops_account_id: str,
- filter_ops_context_change_id: typing.Optional[str] = None,
- filter_ops_context_request_id: typing.Optional[str] = None,
- filter_ops_context_trace_id: typing.Optional[str] = None,
- filter_ops_context_session_id: typing.Optional[str] = None,
- filter_ops_context_actor: typing.Optional[str] = None,
- filter_ops_context_actor_type: typing.Optional[
- AuditServiceListAuditEventsRequestFilterOpsContextActorType
- ] = None,
- filter_ops_context_access_type: typing.Optional[
- AuditServiceListAuditEventsRequestFilterOpsContextAccessType
- ] = None,
- filter_ops_context_ip_address: typing.Optional[str] = None,
- filter_ops_context_origin: typing.Optional[str] = None,
- filter_ops_context_auth_mode: typing.Optional[
- AuditServiceListAuditEventsRequestFilterOpsContextAuthMode
- ] = None,
- filter_ops_context_jwt_id: typing.Optional[str] = None,
- filter_ops_context_bearer_token_context_id: typing.Optional[str] = None,
- filter_ops_parent_account_id: typing.Optional[str] = None,
- filter_ops_workspace_id: typing.Optional[str] = None,
- filter_ops_vault_id: typing.Optional[str] = None,
- filter_ops_resource_i_ds: typing.Optional[str] = None,
- filter_ops_action_type: typing.Optional[AuditServiceListAuditEventsRequestFilterOpsActionType] = None,
- filter_ops_resource_type: typing.Optional[AuditServiceListAuditEventsRequestFilterOpsResourceType] = None,
- filter_ops_tags: typing.Optional[str] = None,
- filter_ops_response_code: typing.Optional[int] = None,
- filter_ops_start_time: typing.Optional[str] = None,
- filter_ops_end_time: typing.Optional[str] = None,
- filter_ops_api_name: typing.Optional[str] = None,
- filter_ops_response_message: typing.Optional[str] = None,
- filter_ops_http_method: typing.Optional[str] = None,
- filter_ops_http_uri: typing.Optional[str] = None,
- sort_ops_sort_by: typing.Optional[str] = None,
- sort_ops_order_by: typing.Optional[AuditServiceListAuditEventsRequestSortOpsOrderBy] = None,
- after_ops_timestamp: typing.Optional[str] = None,
- after_ops_change_id: typing.Optional[str] = None,
- limit: typing.Optional[int] = None,
- offset: typing.Optional[int] = None,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[V1AuditResponse]:
- """
- Lists audit events that match query parameters.
-
- Parameters
- ----------
- filter_ops_account_id : str
- Resources with the specified account ID.
-
- filter_ops_context_change_id : typing.Optional[str]
- ID for the audit event.
-
- filter_ops_context_request_id : typing.Optional[str]
- ID for the request that caused the event.
-
- filter_ops_context_trace_id : typing.Optional[str]
- ID for the request set by the service that received the request.
-
- filter_ops_context_session_id : typing.Optional[str]
- ID for the session in which the request was sent.
-
- filter_ops_context_actor : typing.Optional[str]
- Member who sent the request. Depending on `actorType`, this may be a user ID or a service account ID.
-
- filter_ops_context_actor_type : typing.Optional[AuditServiceListAuditEventsRequestFilterOpsContextActorType]
- Type of member who sent the request.
-
- filter_ops_context_access_type : typing.Optional[AuditServiceListAuditEventsRequestFilterOpsContextAccessType]
- Type of access for the request.
-
- filter_ops_context_ip_address : typing.Optional[str]
- IP Address of the client that made the request.
-
- filter_ops_context_origin : typing.Optional[str]
- HTTP Origin request header (including scheme, hostname, and port) of the request.
-
- filter_ops_context_auth_mode : typing.Optional[AuditServiceListAuditEventsRequestFilterOpsContextAuthMode]
- Authentication mode the `actor` used.
-
- filter_ops_context_jwt_id : typing.Optional[str]
- ID of the JWT token.
-
- filter_ops_context_bearer_token_context_id : typing.Optional[str]
- Embedded User Context.
-
- filter_ops_parent_account_id : typing.Optional[str]
- Resources with the specified parent account ID.
-
- filter_ops_workspace_id : typing.Optional[str]
- Resources with the specified workspace ID.
-
- filter_ops_vault_id : typing.Optional[str]
- Resources with the specified vault ID.
-
- filter_ops_resource_i_ds : typing.Optional[str]
- Resources with a specified ID. If a resource matches at least one ID, the associated event is returned. Format is a comma-separated list of "\/\". For example, "VAULT/12345, USER/67890".
-
- filter_ops_action_type : typing.Optional[AuditServiceListAuditEventsRequestFilterOpsActionType]
- Events with the specified action type.
-
- filter_ops_resource_type : typing.Optional[AuditServiceListAuditEventsRequestFilterOpsResourceType]
- Resources with the specified type.
-
- filter_ops_tags : typing.Optional[str]
- Events with associated tags. If an event matches at least one tag, the event is returned. Comma-separated list. For example, "login, get".
-
- filter_ops_response_code : typing.Optional[int]
- HTTP response code of the request.
-
- filter_ops_start_time : typing.Optional[str]
- Start timestamp for the query, in SQL format.
-
- filter_ops_end_time : typing.Optional[str]
- End timestamp for the query, in SQL format.
-
- filter_ops_api_name : typing.Optional[str]
- Name of the API called in the request.
-
- filter_ops_response_message : typing.Optional[str]
- Response message of the request.
-
- filter_ops_http_method : typing.Optional[str]
- HTTP method of the request.
-
- filter_ops_http_uri : typing.Optional[str]
- HTTP URI of the request.
-
- sort_ops_sort_by : typing.Optional[str]
- Fully-qualified field by which to sort results. Field names should be in camel case (for example, "capitalization.camelCase").
-
- sort_ops_order_by : typing.Optional[AuditServiceListAuditEventsRequestSortOpsOrderBy]
- Ascending or descending ordering of results.
-
- after_ops_timestamp : typing.Optional[str]
- Timestamp provided in the previous audit response's `nextOps` attribute. An alternate way to manage response pagination. Can't be used with `sortOps` or `offset`. For the first request in a series of audit requests, leave blank.
-
- after_ops_change_id : typing.Optional[str]
- Change ID provided in the previous audit response's `nextOps` attribute. An alternate way to manage response pagination. Can't be used with `sortOps` or `offset`. For the first request in a series of audit requests, leave blank.
-
- limit : typing.Optional[int]
- Number of results to return.
-
- offset : typing.Optional[int]
- Record position at which to start returning results.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- HttpResponse[V1AuditResponse]
- A successful response.
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/audit/events",
- method="GET",
- params={
- "filterOps.context.changeID": filter_ops_context_change_id,
- "filterOps.context.requestID": filter_ops_context_request_id,
- "filterOps.context.traceID": filter_ops_context_trace_id,
- "filterOps.context.sessionID": filter_ops_context_session_id,
- "filterOps.context.actor": filter_ops_context_actor,
- "filterOps.context.actorType": filter_ops_context_actor_type,
- "filterOps.context.accessType": filter_ops_context_access_type,
- "filterOps.context.ipAddress": filter_ops_context_ip_address,
- "filterOps.context.origin": filter_ops_context_origin,
- "filterOps.context.authMode": filter_ops_context_auth_mode,
- "filterOps.context.jwtID": filter_ops_context_jwt_id,
- "filterOps.context.bearerTokenContextID": filter_ops_context_bearer_token_context_id,
- "filterOps.parentAccountID": filter_ops_parent_account_id,
- "filterOps.accountID": filter_ops_account_id,
- "filterOps.workspaceID": filter_ops_workspace_id,
- "filterOps.vaultID": filter_ops_vault_id,
- "filterOps.resourceIDs": filter_ops_resource_i_ds,
- "filterOps.actionType": filter_ops_action_type,
- "filterOps.resourceType": filter_ops_resource_type,
- "filterOps.tags": filter_ops_tags,
- "filterOps.responseCode": filter_ops_response_code,
- "filterOps.startTime": filter_ops_start_time,
- "filterOps.endTime": filter_ops_end_time,
- "filterOps.apiName": filter_ops_api_name,
- "filterOps.responseMessage": filter_ops_response_message,
- "filterOps.httpMethod": filter_ops_http_method,
- "filterOps.httpURI": filter_ops_http_uri,
- "sortOps.sortBy": sort_ops_sort_by,
- "sortOps.orderBy": sort_ops_order_by,
- "afterOps.timestamp": after_ops_timestamp,
- "afterOps.changeID": after_ops_change_id,
- "limit": limit,
- "offset": offset,
- },
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- V1AuditResponse,
- parse_obj_as(
- type_=V1AuditResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return HttpResponse(response=_response, data=_data)
- if _response.status_code == 404:
- raise NotFoundError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
-
-class AsyncRawAuditClient:
- def __init__(self, *, client_wrapper: AsyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- async def audit_service_list_audit_events(
- self,
- *,
- filter_ops_account_id: str,
- filter_ops_context_change_id: typing.Optional[str] = None,
- filter_ops_context_request_id: typing.Optional[str] = None,
- filter_ops_context_trace_id: typing.Optional[str] = None,
- filter_ops_context_session_id: typing.Optional[str] = None,
- filter_ops_context_actor: typing.Optional[str] = None,
- filter_ops_context_actor_type: typing.Optional[
- AuditServiceListAuditEventsRequestFilterOpsContextActorType
- ] = None,
- filter_ops_context_access_type: typing.Optional[
- AuditServiceListAuditEventsRequestFilterOpsContextAccessType
- ] = None,
- filter_ops_context_ip_address: typing.Optional[str] = None,
- filter_ops_context_origin: typing.Optional[str] = None,
- filter_ops_context_auth_mode: typing.Optional[
- AuditServiceListAuditEventsRequestFilterOpsContextAuthMode
- ] = None,
- filter_ops_context_jwt_id: typing.Optional[str] = None,
- filter_ops_context_bearer_token_context_id: typing.Optional[str] = None,
- filter_ops_parent_account_id: typing.Optional[str] = None,
- filter_ops_workspace_id: typing.Optional[str] = None,
- filter_ops_vault_id: typing.Optional[str] = None,
- filter_ops_resource_i_ds: typing.Optional[str] = None,
- filter_ops_action_type: typing.Optional[AuditServiceListAuditEventsRequestFilterOpsActionType] = None,
- filter_ops_resource_type: typing.Optional[AuditServiceListAuditEventsRequestFilterOpsResourceType] = None,
- filter_ops_tags: typing.Optional[str] = None,
- filter_ops_response_code: typing.Optional[int] = None,
- filter_ops_start_time: typing.Optional[str] = None,
- filter_ops_end_time: typing.Optional[str] = None,
- filter_ops_api_name: typing.Optional[str] = None,
- filter_ops_response_message: typing.Optional[str] = None,
- filter_ops_http_method: typing.Optional[str] = None,
- filter_ops_http_uri: typing.Optional[str] = None,
- sort_ops_sort_by: typing.Optional[str] = None,
- sort_ops_order_by: typing.Optional[AuditServiceListAuditEventsRequestSortOpsOrderBy] = None,
- after_ops_timestamp: typing.Optional[str] = None,
- after_ops_change_id: typing.Optional[str] = None,
- limit: typing.Optional[int] = None,
- offset: typing.Optional[int] = None,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[V1AuditResponse]:
- """
- Lists audit events that match query parameters.
-
- Parameters
- ----------
- filter_ops_account_id : str
- Resources with the specified account ID.
-
- filter_ops_context_change_id : typing.Optional[str]
- ID for the audit event.
-
- filter_ops_context_request_id : typing.Optional[str]
- ID for the request that caused the event.
-
- filter_ops_context_trace_id : typing.Optional[str]
- ID for the request set by the service that received the request.
-
- filter_ops_context_session_id : typing.Optional[str]
- ID for the session in which the request was sent.
-
- filter_ops_context_actor : typing.Optional[str]
- Member who sent the request. Depending on `actorType`, this may be a user ID or a service account ID.
-
- filter_ops_context_actor_type : typing.Optional[AuditServiceListAuditEventsRequestFilterOpsContextActorType]
- Type of member who sent the request.
-
- filter_ops_context_access_type : typing.Optional[AuditServiceListAuditEventsRequestFilterOpsContextAccessType]
- Type of access for the request.
-
- filter_ops_context_ip_address : typing.Optional[str]
- IP Address of the client that made the request.
-
- filter_ops_context_origin : typing.Optional[str]
- HTTP Origin request header (including scheme, hostname, and port) of the request.
-
- filter_ops_context_auth_mode : typing.Optional[AuditServiceListAuditEventsRequestFilterOpsContextAuthMode]
- Authentication mode the `actor` used.
-
- filter_ops_context_jwt_id : typing.Optional[str]
- ID of the JWT token.
-
- filter_ops_context_bearer_token_context_id : typing.Optional[str]
- Embedded User Context.
-
- filter_ops_parent_account_id : typing.Optional[str]
- Resources with the specified parent account ID.
-
- filter_ops_workspace_id : typing.Optional[str]
- Resources with the specified workspace ID.
-
- filter_ops_vault_id : typing.Optional[str]
- Resources with the specified vault ID.
-
- filter_ops_resource_i_ds : typing.Optional[str]
- Resources with a specified ID. If a resource matches at least one ID, the associated event is returned. Format is a comma-separated list of "\/\". For example, "VAULT/12345, USER/67890".
-
- filter_ops_action_type : typing.Optional[AuditServiceListAuditEventsRequestFilterOpsActionType]
- Events with the specified action type.
-
- filter_ops_resource_type : typing.Optional[AuditServiceListAuditEventsRequestFilterOpsResourceType]
- Resources with the specified type.
-
- filter_ops_tags : typing.Optional[str]
- Events with associated tags. If an event matches at least one tag, the event is returned. Comma-separated list. For example, "login, get".
-
- filter_ops_response_code : typing.Optional[int]
- HTTP response code of the request.
-
- filter_ops_start_time : typing.Optional[str]
- Start timestamp for the query, in SQL format.
-
- filter_ops_end_time : typing.Optional[str]
- End timestamp for the query, in SQL format.
-
- filter_ops_api_name : typing.Optional[str]
- Name of the API called in the request.
-
- filter_ops_response_message : typing.Optional[str]
- Response message of the request.
-
- filter_ops_http_method : typing.Optional[str]
- HTTP method of the request.
-
- filter_ops_http_uri : typing.Optional[str]
- HTTP URI of the request.
-
- sort_ops_sort_by : typing.Optional[str]
- Fully-qualified field by which to sort results. Field names should be in camel case (for example, "capitalization.camelCase").
-
- sort_ops_order_by : typing.Optional[AuditServiceListAuditEventsRequestSortOpsOrderBy]
- Ascending or descending ordering of results.
-
- after_ops_timestamp : typing.Optional[str]
- Timestamp provided in the previous audit response's `nextOps` attribute. An alternate way to manage response pagination. Can't be used with `sortOps` or `offset`. For the first request in a series of audit requests, leave blank.
-
- after_ops_change_id : typing.Optional[str]
- Change ID provided in the previous audit response's `nextOps` attribute. An alternate way to manage response pagination. Can't be used with `sortOps` or `offset`. For the first request in a series of audit requests, leave blank.
-
- limit : typing.Optional[int]
- Number of results to return.
-
- offset : typing.Optional[int]
- Record position at which to start returning results.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AsyncHttpResponse[V1AuditResponse]
- A successful response.
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/audit/events",
- method="GET",
- params={
- "filterOps.context.changeID": filter_ops_context_change_id,
- "filterOps.context.requestID": filter_ops_context_request_id,
- "filterOps.context.traceID": filter_ops_context_trace_id,
- "filterOps.context.sessionID": filter_ops_context_session_id,
- "filterOps.context.actor": filter_ops_context_actor,
- "filterOps.context.actorType": filter_ops_context_actor_type,
- "filterOps.context.accessType": filter_ops_context_access_type,
- "filterOps.context.ipAddress": filter_ops_context_ip_address,
- "filterOps.context.origin": filter_ops_context_origin,
- "filterOps.context.authMode": filter_ops_context_auth_mode,
- "filterOps.context.jwtID": filter_ops_context_jwt_id,
- "filterOps.context.bearerTokenContextID": filter_ops_context_bearer_token_context_id,
- "filterOps.parentAccountID": filter_ops_parent_account_id,
- "filterOps.accountID": filter_ops_account_id,
- "filterOps.workspaceID": filter_ops_workspace_id,
- "filterOps.vaultID": filter_ops_vault_id,
- "filterOps.resourceIDs": filter_ops_resource_i_ds,
- "filterOps.actionType": filter_ops_action_type,
- "filterOps.resourceType": filter_ops_resource_type,
- "filterOps.tags": filter_ops_tags,
- "filterOps.responseCode": filter_ops_response_code,
- "filterOps.startTime": filter_ops_start_time,
- "filterOps.endTime": filter_ops_end_time,
- "filterOps.apiName": filter_ops_api_name,
- "filterOps.responseMessage": filter_ops_response_message,
- "filterOps.httpMethod": filter_ops_http_method,
- "filterOps.httpURI": filter_ops_http_uri,
- "sortOps.sortBy": sort_ops_sort_by,
- "sortOps.orderBy": sort_ops_order_by,
- "afterOps.timestamp": after_ops_timestamp,
- "afterOps.changeID": after_ops_change_id,
- "limit": limit,
- "offset": offset,
- },
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- V1AuditResponse,
- parse_obj_as(
- type_=V1AuditResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return AsyncHttpResponse(response=_response, data=_data)
- if _response.status_code == 404:
- raise NotFoundError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/skyvault/skyflow/generated/rest/audit/types/__init__.py b/skyvault/skyflow/generated/rest/audit/types/__init__.py
deleted file mode 100644
index 71e29b43..00000000
--- a/skyvault/skyflow/generated/rest/audit/types/__init__.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-# isort: skip_file
-
-from .audit_service_list_audit_events_request_filter_ops_action_type import (
- AuditServiceListAuditEventsRequestFilterOpsActionType,
-)
-from .audit_service_list_audit_events_request_filter_ops_context_access_type import (
- AuditServiceListAuditEventsRequestFilterOpsContextAccessType,
-)
-from .audit_service_list_audit_events_request_filter_ops_context_actor_type import (
- AuditServiceListAuditEventsRequestFilterOpsContextActorType,
-)
-from .audit_service_list_audit_events_request_filter_ops_context_auth_mode import (
- AuditServiceListAuditEventsRequestFilterOpsContextAuthMode,
-)
-from .audit_service_list_audit_events_request_filter_ops_resource_type import (
- AuditServiceListAuditEventsRequestFilterOpsResourceType,
-)
-from .audit_service_list_audit_events_request_sort_ops_order_by import AuditServiceListAuditEventsRequestSortOpsOrderBy
-
-__all__ = [
- "AuditServiceListAuditEventsRequestFilterOpsActionType",
- "AuditServiceListAuditEventsRequestFilterOpsContextAccessType",
- "AuditServiceListAuditEventsRequestFilterOpsContextActorType",
- "AuditServiceListAuditEventsRequestFilterOpsContextAuthMode",
- "AuditServiceListAuditEventsRequestFilterOpsResourceType",
- "AuditServiceListAuditEventsRequestSortOpsOrderBy",
-]
diff --git a/skyvault/skyflow/generated/rest/audit/types/audit_service_list_audit_events_request_filter_ops_action_type.py b/skyvault/skyflow/generated/rest/audit/types/audit_service_list_audit_events_request_filter_ops_action_type.py
deleted file mode 100644
index 24df22e1..00000000
--- a/skyvault/skyflow/generated/rest/audit/types/audit_service_list_audit_events_request_filter_ops_action_type.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-AuditServiceListAuditEventsRequestFilterOpsActionType = typing.Union[
- typing.Literal[
- "NONE",
- "ASSIGN",
- "CREATE",
- "DELETE",
- "EXECUTE",
- "LIST",
- "READ",
- "UNASSIGN",
- "UPDATE",
- "VALIDATE",
- "LOGIN",
- "ROTATE",
- "SCHEDULEROTATION",
- "SCHEDULEROTATIONALERT",
- "IMPORT",
- "GETIMPORTPARAMETERS",
- "PING",
- "GETCLOUDPROVIDER",
- ],
- typing.Any,
-]
diff --git a/skyvault/skyflow/generated/rest/audit/types/audit_service_list_audit_events_request_filter_ops_context_access_type.py b/skyvault/skyflow/generated/rest/audit/types/audit_service_list_audit_events_request_filter_ops_context_access_type.py
deleted file mode 100644
index 1349c539..00000000
--- a/skyvault/skyflow/generated/rest/audit/types/audit_service_list_audit_events_request_filter_ops_context_access_type.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-AuditServiceListAuditEventsRequestFilterOpsContextAccessType = typing.Union[
- typing.Literal["ACCESS_NONE", "API", "SQL", "OKTA_LOGIN"], typing.Any
-]
diff --git a/skyvault/skyflow/generated/rest/audit/types/audit_service_list_audit_events_request_filter_ops_context_actor_type.py b/skyvault/skyflow/generated/rest/audit/types/audit_service_list_audit_events_request_filter_ops_context_actor_type.py
deleted file mode 100644
index 4a5a96f1..00000000
--- a/skyvault/skyflow/generated/rest/audit/types/audit_service_list_audit_events_request_filter_ops_context_actor_type.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-AuditServiceListAuditEventsRequestFilterOpsContextActorType = typing.Union[
- typing.Literal["NONE", "USER", "SERVICE_ACCOUNT"], typing.Any
-]
diff --git a/skyvault/skyflow/generated/rest/audit/types/audit_service_list_audit_events_request_filter_ops_context_auth_mode.py b/skyvault/skyflow/generated/rest/audit/types/audit_service_list_audit_events_request_filter_ops_context_auth_mode.py
deleted file mode 100644
index f542f677..00000000
--- a/skyvault/skyflow/generated/rest/audit/types/audit_service_list_audit_events_request_filter_ops_context_auth_mode.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-AuditServiceListAuditEventsRequestFilterOpsContextAuthMode = typing.Union[
- typing.Literal["AUTH_NONE", "OKTA_JWT", "SERVICE_ACCOUNT_JWT", "PAT_JWT"], typing.Any
-]
diff --git a/skyvault/skyflow/generated/rest/audit/types/audit_service_list_audit_events_request_filter_ops_resource_type.py b/skyvault/skyflow/generated/rest/audit/types/audit_service_list_audit_events_request_filter_ops_resource_type.py
deleted file mode 100644
index 610aa1e6..00000000
--- a/skyvault/skyflow/generated/rest/audit/types/audit_service_list_audit_events_request_filter_ops_resource_type.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-AuditServiceListAuditEventsRequestFilterOpsResourceType = typing.Union[
- typing.Literal[
- "NONE_API",
- "ACCOUNT",
- "AUDIT",
- "BASE_DATA_TYPE",
- "FIELD_TEMPLATE",
- "FILE",
- "KEY",
- "POLICY",
- "PROTO_PARSE",
- "RECORD",
- "ROLE",
- "RULE",
- "SECRET",
- "SERVICE_ACCOUNT",
- "TOKEN",
- "USER",
- "VAULT",
- "VAULT_TEMPLATE",
- "WORKSPACE",
- "TABLE",
- "POLICY_TEMPLATE",
- "MEMBER",
- "TAG",
- "CONNECTION",
- "MIGRATION",
- "SCHEDULED_JOB",
- "JOB",
- "COLUMN_NAME",
- "NETWORK_TOKEN",
- "SUBSCRIPTION",
- ],
- typing.Any,
-]
diff --git a/skyvault/skyflow/generated/rest/audit/types/audit_service_list_audit_events_request_sort_ops_order_by.py b/skyvault/skyflow/generated/rest/audit/types/audit_service_list_audit_events_request_sort_ops_order_by.py
deleted file mode 100644
index 48a79484..00000000
--- a/skyvault/skyflow/generated/rest/audit/types/audit_service_list_audit_events_request_sort_ops_order_by.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-AuditServiceListAuditEventsRequestSortOpsOrderBy = typing.Union[typing.Literal["ASCENDING", "DESCENDING"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/authentication/client.py b/skyvault/skyflow/generated/rest/authentication/client.py
deleted file mode 100644
index 99ff6aef..00000000
--- a/skyvault/skyflow/generated/rest/authentication/client.py
+++ /dev/null
@@ -1,181 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
-from ..core.request_options import RequestOptions
-from ..types.v_1_get_auth_token_response import V1GetAuthTokenResponse
-from .raw_client import AsyncRawAuthenticationClient, RawAuthenticationClient
-
-# this is used as the default value for optional parameters
-OMIT = typing.cast(typing.Any, ...)
-
-
-class AuthenticationClient:
- def __init__(self, *, client_wrapper: SyncClientWrapper):
- self._raw_client = RawAuthenticationClient(client_wrapper=client_wrapper)
-
- @property
- def with_raw_response(self) -> RawAuthenticationClient:
- """
- Retrieves a raw implementation of this client that returns raw responses.
-
- Returns
- -------
- RawAuthenticationClient
- """
- return self._raw_client
-
- def authentication_service_get_auth_token(
- self,
- *,
- grant_type: str,
- assertion: str,
- subject_token: typing.Optional[str] = OMIT,
- subject_token_type: typing.Optional[str] = OMIT,
- requested_token_use: typing.Optional[str] = OMIT,
- scope: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> V1GetAuthTokenResponse:
- """
- Generates a Bearer Token to authenticate with Skyflow. This method doesn't require the Authorization header.
Note: For recommended ways to authenticate, see API authentication.
-
- Parameters
- ----------
- grant_type : str
- Grant type of the request. Set this to `urn:ietf:params:oauth:grant-type:jwt-bearer`.
-
- assertion : str
- User-signed JWT token that contains the following fields:
iss: Issuer of the JWT.key: Unique identifier for the key.aud: Recipient the JWT is intended for.exp: Time the JWT expires.sub: Subject of the JWT.ctx: (Optional) Value for Context-aware authorization.
-
- subject_token : typing.Optional[str]
- Subject token.
-
- subject_token_type : typing.Optional[str]
- Subject token type.
-
- requested_token_use : typing.Optional[str]
- Token use type. Either `delegation` or `impersonation`.
-
- scope : typing.Optional[str]
- Subset of available roles to associate with the requested token. Uses the format "role:\ role:\".
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- V1GetAuthTokenResponse
- A successful response.
-
- Examples
- --------
- from skyflow import Skyflow
-
- client = Skyflow(
- token="",
- )
- client.authentication.authentication_service_get_auth_token(
- grant_type="urn:ietf:params:oauth:grant-type:jwt-bearer",
- assertion="",
- )
- """
- _response = self._raw_client.authentication_service_get_auth_token(
- grant_type=grant_type,
- assertion=assertion,
- subject_token=subject_token,
- subject_token_type=subject_token_type,
- requested_token_use=requested_token_use,
- scope=scope,
- request_options=request_options,
- )
- return _response.data
-
-
-class AsyncAuthenticationClient:
- def __init__(self, *, client_wrapper: AsyncClientWrapper):
- self._raw_client = AsyncRawAuthenticationClient(client_wrapper=client_wrapper)
-
- @property
- def with_raw_response(self) -> AsyncRawAuthenticationClient:
- """
- Retrieves a raw implementation of this client that returns raw responses.
-
- Returns
- -------
- AsyncRawAuthenticationClient
- """
- return self._raw_client
-
- async def authentication_service_get_auth_token(
- self,
- *,
- grant_type: str,
- assertion: str,
- subject_token: typing.Optional[str] = OMIT,
- subject_token_type: typing.Optional[str] = OMIT,
- requested_token_use: typing.Optional[str] = OMIT,
- scope: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> V1GetAuthTokenResponse:
- """
- Generates a Bearer Token to authenticate with Skyflow. This method doesn't require the Authorization header.
Note: For recommended ways to authenticate, see API authentication.
-
- Parameters
- ----------
- grant_type : str
- Grant type of the request. Set this to `urn:ietf:params:oauth:grant-type:jwt-bearer`.
-
- assertion : str
- User-signed JWT token that contains the following fields:
iss: Issuer of the JWT.key: Unique identifier for the key.aud: Recipient the JWT is intended for.exp: Time the JWT expires.sub: Subject of the JWT.ctx: (Optional) Value for Context-aware authorization.
-
- subject_token : typing.Optional[str]
- Subject token.
-
- subject_token_type : typing.Optional[str]
- Subject token type.
-
- requested_token_use : typing.Optional[str]
- Token use type. Either `delegation` or `impersonation`.
-
- scope : typing.Optional[str]
- Subset of available roles to associate with the requested token. Uses the format "role:\ role:\".
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- V1GetAuthTokenResponse
- A successful response.
-
- Examples
- --------
- import asyncio
-
- from skyflow import AsyncSkyflow
-
- client = AsyncSkyflow(
- token="",
- )
-
-
- async def main() -> None:
- await client.authentication.authentication_service_get_auth_token(
- grant_type="urn:ietf:params:oauth:grant-type:jwt-bearer",
- assertion="",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._raw_client.authentication_service_get_auth_token(
- grant_type=grant_type,
- assertion=assertion,
- subject_token=subject_token,
- subject_token_type=subject_token_type,
- requested_token_use=requested_token_use,
- scope=scope,
- request_options=request_options,
- )
- return _response.data
diff --git a/skyvault/skyflow/generated/rest/bin_lookup/client.py b/skyvault/skyflow/generated/rest/bin_lookup/client.py
deleted file mode 100644
index fe8c892a..00000000
--- a/skyvault/skyflow/generated/rest/bin_lookup/client.py
+++ /dev/null
@@ -1,158 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
-from ..core.request_options import RequestOptions
-from ..types.v_1_bin_list_response import V1BinListResponse
-from ..types.v_1_vault_schema_config import V1VaultSchemaConfig
-from .raw_client import AsyncRawBinLookupClient, RawBinLookupClient
-
-# this is used as the default value for optional parameters
-OMIT = typing.cast(typing.Any, ...)
-
-
-class BinLookupClient:
- def __init__(self, *, client_wrapper: SyncClientWrapper):
- self._raw_client = RawBinLookupClient(client_wrapper=client_wrapper)
-
- @property
- def with_raw_response(self) -> RawBinLookupClient:
- """
- Retrieves a raw implementation of this client that returns raw responses.
-
- Returns
- -------
- RawBinLookupClient
- """
- return self._raw_client
-
- def bin_list_service_list_cards_of_bin(
- self,
- *,
- fields: typing.Optional[typing.Sequence[str]] = OMIT,
- bin: typing.Optional[str] = OMIT,
- vault_schema_config: typing.Optional[V1VaultSchemaConfig] = OMIT,
- skyflow_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> V1BinListResponse:
- """
- Note: This endpoint is in beta and subject to change.
Returns the specified card metadata.
-
- Parameters
- ----------
- fields : typing.Optional[typing.Sequence[str]]
- Fields to return. If not specified, all fields are returned.
-
- bin : typing.Optional[str]
- BIN of the card.
-
- vault_schema_config : typing.Optional[V1VaultSchemaConfig]
-
- skyflow_id : typing.Optional[str]
- skyflow_id of the record.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- V1BinListResponse
- A successful response.
-
- Examples
- --------
- from skyflow import Skyflow
-
- client = Skyflow(
- token="YOUR_TOKEN",
- )
- client.bin_lookup.bin_list_service_list_cards_of_bin(
- bin="012345",
- )
- """
- _response = self._raw_client.bin_list_service_list_cards_of_bin(
- fields=fields,
- bin=bin,
- vault_schema_config=vault_schema_config,
- skyflow_id=skyflow_id,
- request_options=request_options,
- )
- return _response.data
-
-
-class AsyncBinLookupClient:
- def __init__(self, *, client_wrapper: AsyncClientWrapper):
- self._raw_client = AsyncRawBinLookupClient(client_wrapper=client_wrapper)
-
- @property
- def with_raw_response(self) -> AsyncRawBinLookupClient:
- """
- Retrieves a raw implementation of this client that returns raw responses.
-
- Returns
- -------
- AsyncRawBinLookupClient
- """
- return self._raw_client
-
- async def bin_list_service_list_cards_of_bin(
- self,
- *,
- fields: typing.Optional[typing.Sequence[str]] = OMIT,
- bin: typing.Optional[str] = OMIT,
- vault_schema_config: typing.Optional[V1VaultSchemaConfig] = OMIT,
- skyflow_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> V1BinListResponse:
- """
- Note: This endpoint is in beta and subject to change.
Returns the specified card metadata.
-
- Parameters
- ----------
- fields : typing.Optional[typing.Sequence[str]]
- Fields to return. If not specified, all fields are returned.
-
- bin : typing.Optional[str]
- BIN of the card.
-
- vault_schema_config : typing.Optional[V1VaultSchemaConfig]
-
- skyflow_id : typing.Optional[str]
- skyflow_id of the record.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- V1BinListResponse
- A successful response.
-
- Examples
- --------
- import asyncio
-
- from skyflow import AsyncSkyflow
-
- client = AsyncSkyflow(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.bin_lookup.bin_list_service_list_cards_of_bin(
- bin="012345",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._raw_client.bin_list_service_list_cards_of_bin(
- fields=fields,
- bin=bin,
- vault_schema_config=vault_schema_config,
- skyflow_id=skyflow_id,
- request_options=request_options,
- )
- return _response.data
diff --git a/skyvault/skyflow/generated/rest/bin_lookup/raw_client.py b/skyvault/skyflow/generated/rest/bin_lookup/raw_client.py
deleted file mode 100644
index b82f4c84..00000000
--- a/skyvault/skyflow/generated/rest/bin_lookup/raw_client.py
+++ /dev/null
@@ -1,179 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-from json.decoder import JSONDecodeError
-
-from ..core.api_error import ApiError
-from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
-from ..core.http_response import AsyncHttpResponse, HttpResponse
-from ..core.pydantic_utilities import parse_obj_as
-from ..core.request_options import RequestOptions
-from ..core.serialization import convert_and_respect_annotation_metadata
-from ..errors.not_found_error import NotFoundError
-from ..types.v_1_bin_list_response import V1BinListResponse
-from ..types.v_1_vault_schema_config import V1VaultSchemaConfig
-
-# this is used as the default value for optional parameters
-OMIT = typing.cast(typing.Any, ...)
-
-
-class RawBinLookupClient:
- def __init__(self, *, client_wrapper: SyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- def bin_list_service_list_cards_of_bin(
- self,
- *,
- fields: typing.Optional[typing.Sequence[str]] = OMIT,
- bin: typing.Optional[str] = OMIT,
- vault_schema_config: typing.Optional[V1VaultSchemaConfig] = OMIT,
- skyflow_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[V1BinListResponse]:
- """
- Note: This endpoint is in beta and subject to change.
Returns the specified card metadata.
-
- Parameters
- ----------
- fields : typing.Optional[typing.Sequence[str]]
- Fields to return. If not specified, all fields are returned.
-
- bin : typing.Optional[str]
- BIN of the card.
-
- vault_schema_config : typing.Optional[V1VaultSchemaConfig]
-
- skyflow_id : typing.Optional[str]
- skyflow_id of the record.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- HttpResponse[V1BinListResponse]
- A successful response.
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/card_lookup",
- method="POST",
- json={
- "fields": fields,
- "BIN": bin,
- "vault_schema_config": convert_and_respect_annotation_metadata(
- object_=vault_schema_config, annotation=V1VaultSchemaConfig, direction="write"
- ),
- "skyflow_id": skyflow_id,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- V1BinListResponse,
- parse_obj_as(
- type_=V1BinListResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return HttpResponse(response=_response, data=_data)
- if _response.status_code == 404:
- raise NotFoundError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
-
-class AsyncRawBinLookupClient:
- def __init__(self, *, client_wrapper: AsyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- async def bin_list_service_list_cards_of_bin(
- self,
- *,
- fields: typing.Optional[typing.Sequence[str]] = OMIT,
- bin: typing.Optional[str] = OMIT,
- vault_schema_config: typing.Optional[V1VaultSchemaConfig] = OMIT,
- skyflow_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[V1BinListResponse]:
- """
- Note: This endpoint is in beta and subject to change.
Returns the specified card metadata.
-
- Parameters
- ----------
- fields : typing.Optional[typing.Sequence[str]]
- Fields to return. If not specified, all fields are returned.
-
- bin : typing.Optional[str]
- BIN of the card.
-
- vault_schema_config : typing.Optional[V1VaultSchemaConfig]
-
- skyflow_id : typing.Optional[str]
- skyflow_id of the record.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AsyncHttpResponse[V1BinListResponse]
- A successful response.
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/card_lookup",
- method="POST",
- json={
- "fields": fields,
- "BIN": bin,
- "vault_schema_config": convert_and_respect_annotation_metadata(
- object_=vault_schema_config, annotation=V1VaultSchemaConfig, direction="write"
- ),
- "skyflow_id": skyflow_id,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- V1BinListResponse,
- parse_obj_as(
- type_=V1BinListResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return AsyncHttpResponse(response=_response, data=_data)
- if _response.status_code == 404:
- raise NotFoundError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/skyvault/skyflow/generated/rest/client.py b/skyvault/skyflow/generated/rest/client.py
index e8abdf54..1d896ec7 100644
--- a/skyvault/skyflow/generated/rest/client.py
+++ b/skyvault/skyflow/generated/rest/client.py
@@ -1,22 +1,24 @@
# This file was auto-generated by Fern from our API Definition.
+from __future__ import annotations
+
import typing
import httpx
-from .audit.client import AsyncAuditClient, AuditClient
-from .authentication.client import AsyncAuthenticationClient, AuthenticationClient
-from .bin_lookup.client import AsyncBinLookupClient, BinLookupClient
from .core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
-from .environment import SkyflowEnvironment
-from .files.client import AsyncFilesClient, FilesClient
-from .guardrails.client import AsyncGuardrailsClient, GuardrailsClient
-from .query.client import AsyncQueryClient, QueryClient
-from .records.client import AsyncRecordsClient, RecordsClient
-from .strings.client import AsyncStringsClient, StringsClient
-from .tokens.client import AsyncTokensClient, TokensClient
+from .core.logging import LogConfig, Logger
+from .core.request_options import RequestOptions
+from .environment import SkyflowAuthEnvironment
+from .raw_client import AsyncRawSkyflowAuth, RawSkyflowAuth
+
+if typing.TYPE_CHECKING:
+ from .files.client import AsyncFilesClient, FilesClient
+ from .query.client import AsyncQueryClient, QueryClient
+ from .records.client import AsyncRecordsClient, RecordsClient
+ from .tokens.client import AsyncTokensClient, TokensClient
-class Skyflow:
+class SkyflowAuth:
"""
Use this class to access the different functions within the SDK. You can instantiate any number of clients with different configuration that will propagate to these functions.
@@ -25,14 +27,17 @@ class Skyflow:
base_url : typing.Optional[str]
The base url to use for requests from the client.
- environment : SkyflowEnvironment
- The environment to use for requests from the client. from .environment import SkyflowEnvironment
+ environment : SkyflowAuthEnvironment
+ The environment to use for requests from the client. from .environment import SkyflowAuthEnvironment
+
+ Defaults to SkyflowAuthEnvironment.PRODUCTION
- Defaults to SkyflowEnvironment.PRODUCTION
+ identifier : typing.Optional[str]
+ Server URL variable for 'identifier'. Defaults to '{{vault_uri}}'.
token : typing.Optional[typing.Union[str, typing.Callable[[], str]]]
headers : typing.Optional[typing.Dict[str, str]]
@@ -41,17 +46,29 @@ class Skyflow:
timeout : typing.Optional[float]
The timeout to be used, in seconds, for requests. By default the timeout is 60 seconds, unless a custom httpx client is used, in which case this default is not enforced.
+ max_retries : typing.Optional[int]
+ The default maximum number of retries for failed requests. Defaults to 2. Per-request `max_retries` in `request_options` takes precedence over this value.
+
+ stream_reconnection_enabled : typing.Optional[bool]
+ Whether to automatically reconnect on stream disconnection for resumable streaming endpoints. Defaults to True. Per-request `stream_reconnection_enabled` in `request_options` takes precedence over this value.
+
+ max_stream_reconnection_attempts : typing.Optional[int]
+ The maximum number of reconnection attempts for resumable streaming endpoints. Defaults to no limit. Per-request `max_stream_reconnection_attempts` in `request_options` takes precedence over this value.
+
follow_redirects : typing.Optional[bool]
Whether the default httpx client follows redirects or not, this is irrelevant if a custom httpx client is passed in.
httpx_client : typing.Optional[httpx.Client]
The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration.
+ logging : typing.Optional[typing.Union[LogConfig, Logger]]
+ Configure logging for the SDK. Accepts a LogConfig dict with 'level' (debug/info/warn/error), 'logger' (custom logger implementation), and 'silent' (boolean, defaults to True) fields. You can also pass a pre-configured Logger instance.
+
Examples
--------
- from skyflow import Skyflow
+ from skyflow import SkyflowAuth
- client = Skyflow(
+ client = SkyflowAuth(
token="YOUR_TOKEN",
)
"""
@@ -60,16 +77,29 @@ def __init__(
self,
*,
base_url: typing.Optional[str] = None,
- environment: SkyflowEnvironment = SkyflowEnvironment.PRODUCTION,
+ environment: SkyflowAuthEnvironment = SkyflowAuthEnvironment.PRODUCTION,
+ identifier: typing.Optional[str] = None,
token: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = None,
headers: typing.Optional[typing.Dict[str, str]] = None,
timeout: typing.Optional[float] = None,
+ max_retries: typing.Optional[int] = None,
+ stream_reconnection_enabled: typing.Optional[bool] = None,
+ max_stream_reconnection_attempts: typing.Optional[int] = None,
follow_redirects: typing.Optional[bool] = True,
httpx_client: typing.Optional[httpx.Client] = None,
+ logging: typing.Optional[typing.Union[LogConfig, Logger]] = None,
):
- _defaulted_timeout = (
- timeout if timeout is not None else 60 if httpx_client is None else httpx_client.timeout.read
- )
+ _defaulted_timeout = timeout if timeout is not None else 60 if httpx_client is None else None
+ _defaulted_max_retries = max_retries if max_retries is not None else 2
+ if identifier is not None:
+ _identifier = identifier if identifier is not None else "{{vault_uri}}"
+ _environment_url_templates = {
+ SkyflowAuthEnvironment.PRODUCTION: "https://{identifier}.vault.skyflowapis.com",
+ SkyflowAuthEnvironment.SANDBOX: "https://{identifier}.vault.skyflowapis-preview.com",
+ }
+ _url_template = _environment_url_templates.get(environment, "https://{identifier}.vault.skyflowapis.com")
+ if base_url is None:
+ base_url = _url_template.format(identifier=_identifier)
self._client_wrapper = SyncClientWrapper(
base_url=_get_base_url(base_url=base_url, environment=environment),
token=token,
@@ -80,19 +110,107 @@ def __init__(
if follow_redirects is not None
else httpx.Client(timeout=_defaulted_timeout),
timeout=_defaulted_timeout,
+ max_retries=_defaulted_max_retries,
+ stream_reconnection_enabled=stream_reconnection_enabled,
+ max_stream_reconnection_attempts=max_stream_reconnection_attempts,
+ logging=logging,
+ )
+ self._raw_client = RawSkyflowAuth(client_wrapper=self._client_wrapper)
+ self._records: typing.Optional[RecordsClient] = None
+ self._tokens: typing.Optional[TokensClient] = None
+ self._query: typing.Optional[QueryClient] = None
+ self._files: typing.Optional[FilesClient] = None
+
+ @property
+ def with_raw_response(self) -> RawSkyflowAuth:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ RawSkyflowAuth
+ """
+ return self._raw_client
+
+ def patch_v2vaults_id(
+ self, vault_id: typing.Optional[str], *, request_options: typing.Optional[RequestOptions] = None
+ ) -> None:
+ """
+ Parameters
+ ----------
+ vault_id : typing.Optional[str]
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ None
+
+ Examples
+ --------
+ from skyflow import SkyflowAuth
+
+ client = SkyflowAuth(
+ token="YOUR_TOKEN",
)
- self.audit = AuditClient(client_wrapper=self._client_wrapper)
- self.bin_lookup = BinLookupClient(client_wrapper=self._client_wrapper)
- self.records = RecordsClient(client_wrapper=self._client_wrapper)
- self.tokens = TokensClient(client_wrapper=self._client_wrapper)
- self.query = QueryClient(client_wrapper=self._client_wrapper)
- self.authentication = AuthenticationClient(client_wrapper=self._client_wrapper)
- self.files = FilesClient(client_wrapper=self._client_wrapper)
- self.strings = StringsClient(client_wrapper=self._client_wrapper)
- self.guardrails = GuardrailsClient(client_wrapper=self._client_wrapper)
-
-
-class AsyncSkyflow:
+ client.patch_v2vaults_id()
+ """
+ _response = self._raw_client.patch_v2vaults_id(vault_id, request_options=request_options)
+ return _response.data
+
+ @property
+ def records(self):
+ if self._records is None:
+ from .records.client import RecordsClient # noqa: E402
+
+ self._records = RecordsClient(client_wrapper=self._client_wrapper)
+ return self._records
+
+ @property
+ def tokens(self):
+ if self._tokens is None:
+ from .tokens.client import TokensClient # noqa: E402
+
+ self._tokens = TokensClient(client_wrapper=self._client_wrapper)
+ return self._tokens
+
+ @property
+ def query(self):
+ if self._query is None:
+ from .query.client import QueryClient # noqa: E402
+
+ self._query = QueryClient(client_wrapper=self._client_wrapper)
+ return self._query
+
+ @property
+ def files(self):
+ if self._files is None:
+ from .files.client import FilesClient # noqa: E402
+
+ self._files = FilesClient(client_wrapper=self._client_wrapper)
+ return self._files
+
+
+def _make_default_async_client(
+ timeout: typing.Optional[float],
+ follow_redirects: typing.Optional[bool],
+) -> httpx.AsyncClient:
+ try:
+ import httpx_aiohttp # type: ignore[import-not-found]
+ except ImportError:
+ pass
+ else:
+ if follow_redirects is not None:
+ return httpx_aiohttp.HttpxAiohttpClient(timeout=timeout, follow_redirects=follow_redirects)
+ return httpx_aiohttp.HttpxAiohttpClient(timeout=timeout)
+
+ if follow_redirects is not None:
+ return httpx.AsyncClient(timeout=timeout, follow_redirects=follow_redirects)
+ return httpx.AsyncClient(timeout=timeout)
+
+
+class AsyncSkyflowAuth:
"""
Use this class to access the different functions within the SDK. You can instantiate any number of clients with different configuration that will propagate to these functions.
@@ -101,33 +219,51 @@ class AsyncSkyflow:
base_url : typing.Optional[str]
The base url to use for requests from the client.
- environment : SkyflowEnvironment
- The environment to use for requests from the client. from .environment import SkyflowEnvironment
+ environment : SkyflowAuthEnvironment
+ The environment to use for requests from the client. from .environment import SkyflowAuthEnvironment
+
+ Defaults to SkyflowAuthEnvironment.PRODUCTION
- Defaults to SkyflowEnvironment.PRODUCTION
+ identifier : typing.Optional[str]
+ Server URL variable for 'identifier'. Defaults to '{{vault_uri}}'.
token : typing.Optional[typing.Union[str, typing.Callable[[], str]]]
headers : typing.Optional[typing.Dict[str, str]]
Additional headers to send with every request.
+ async_token : typing.Optional[typing.Callable[[], typing.Awaitable[str]]]
+ An async callable that returns a bearer token. Use this when token acquisition involves async I/O (e.g., refreshing tokens via an async HTTP client). When provided, this is used instead of the synchronous token for async requests.
+
timeout : typing.Optional[float]
The timeout to be used, in seconds, for requests. By default the timeout is 60 seconds, unless a custom httpx client is used, in which case this default is not enforced.
+ max_retries : typing.Optional[int]
+ The default maximum number of retries for failed requests. Defaults to 2. Per-request `max_retries` in `request_options` takes precedence over this value.
+
+ stream_reconnection_enabled : typing.Optional[bool]
+ Whether to automatically reconnect on stream disconnection for resumable streaming endpoints. Defaults to True. Per-request `stream_reconnection_enabled` in `request_options` takes precedence over this value.
+
+ max_stream_reconnection_attempts : typing.Optional[int]
+ The maximum number of reconnection attempts for resumable streaming endpoints. Defaults to no limit. Per-request `max_stream_reconnection_attempts` in `request_options` takes precedence over this value.
+
follow_redirects : typing.Optional[bool]
Whether the default httpx client follows redirects or not, this is irrelevant if a custom httpx client is passed in.
httpx_client : typing.Optional[httpx.AsyncClient]
The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration.
+ logging : typing.Optional[typing.Union[LogConfig, Logger]]
+ Configure logging for the SDK. Accepts a LogConfig dict with 'level' (debug/info/warn/error), 'logger' (custom logger implementation), and 'silent' (boolean, defaults to True) fields. You can also pass a pre-configured Logger instance.
+
Examples
--------
- from skyflow import AsyncSkyflow
+ from skyflow import AsyncSkyflowAuth
- client = AsyncSkyflow(
+ client = AsyncSkyflowAuth(
token="YOUR_TOKEN",
)
"""
@@ -136,39 +272,130 @@ def __init__(
self,
*,
base_url: typing.Optional[str] = None,
- environment: SkyflowEnvironment = SkyflowEnvironment.PRODUCTION,
+ environment: SkyflowAuthEnvironment = SkyflowAuthEnvironment.PRODUCTION,
+ identifier: typing.Optional[str] = None,
token: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = None,
headers: typing.Optional[typing.Dict[str, str]] = None,
+ async_token: typing.Optional[typing.Callable[[], typing.Awaitable[str]]] = None,
timeout: typing.Optional[float] = None,
+ max_retries: typing.Optional[int] = None,
+ stream_reconnection_enabled: typing.Optional[bool] = None,
+ max_stream_reconnection_attempts: typing.Optional[int] = None,
follow_redirects: typing.Optional[bool] = True,
httpx_client: typing.Optional[httpx.AsyncClient] = None,
+ logging: typing.Optional[typing.Union[LogConfig, Logger]] = None,
):
- _defaulted_timeout = (
- timeout if timeout is not None else 60 if httpx_client is None else httpx_client.timeout.read
- )
+ _defaulted_timeout = timeout if timeout is not None else 60 if httpx_client is None else None
+ _defaulted_max_retries = max_retries if max_retries is not None else 2
+ if identifier is not None:
+ _identifier = identifier if identifier is not None else "{{vault_uri}}"
+ _environment_url_templates = {
+ SkyflowAuthEnvironment.PRODUCTION: "https://{identifier}.vault.skyflowapis.com",
+ SkyflowAuthEnvironment.SANDBOX: "https://{identifier}.vault.skyflowapis-preview.com",
+ }
+ _url_template = _environment_url_templates.get(environment, "https://{identifier}.vault.skyflowapis.com")
+ if base_url is None:
+ base_url = _url_template.format(identifier=_identifier)
self._client_wrapper = AsyncClientWrapper(
base_url=_get_base_url(base_url=base_url, environment=environment),
token=token,
headers=headers,
+ async_token=async_token,
httpx_client=httpx_client
if httpx_client is not None
- else httpx.AsyncClient(timeout=_defaulted_timeout, follow_redirects=follow_redirects)
- if follow_redirects is not None
- else httpx.AsyncClient(timeout=_defaulted_timeout),
+ else _make_default_async_client(timeout=_defaulted_timeout, follow_redirects=follow_redirects),
timeout=_defaulted_timeout,
+ max_retries=_defaulted_max_retries,
+ stream_reconnection_enabled=stream_reconnection_enabled,
+ max_stream_reconnection_attempts=max_stream_reconnection_attempts,
+ logging=logging,
)
- self.audit = AsyncAuditClient(client_wrapper=self._client_wrapper)
- self.bin_lookup = AsyncBinLookupClient(client_wrapper=self._client_wrapper)
- self.records = AsyncRecordsClient(client_wrapper=self._client_wrapper)
- self.tokens = AsyncTokensClient(client_wrapper=self._client_wrapper)
- self.query = AsyncQueryClient(client_wrapper=self._client_wrapper)
- self.authentication = AsyncAuthenticationClient(client_wrapper=self._client_wrapper)
- self.files = AsyncFilesClient(client_wrapper=self._client_wrapper)
- self.strings = AsyncStringsClient(client_wrapper=self._client_wrapper)
- self.guardrails = AsyncGuardrailsClient(client_wrapper=self._client_wrapper)
-
-
-def _get_base_url(*, base_url: typing.Optional[str] = None, environment: SkyflowEnvironment) -> str:
+ self._raw_client = AsyncRawSkyflowAuth(client_wrapper=self._client_wrapper)
+ self._records: typing.Optional[AsyncRecordsClient] = None
+ self._tokens: typing.Optional[AsyncTokensClient] = None
+ self._query: typing.Optional[AsyncQueryClient] = None
+ self._files: typing.Optional[AsyncFilesClient] = None
+
+ @property
+ def with_raw_response(self) -> AsyncRawSkyflowAuth:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
+
+ Returns
+ -------
+ AsyncRawSkyflowAuth
+ """
+ return self._raw_client
+
+ async def patch_v2vaults_id(
+ self, vault_id: typing.Optional[str], *, request_options: typing.Optional[RequestOptions] = None
+ ) -> None:
+ """
+ Parameters
+ ----------
+ vault_id : typing.Optional[str]
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ None
+
+ Examples
+ --------
+ import asyncio
+
+ from skyflow import AsyncSkyflowAuth
+
+ client = AsyncSkyflowAuth(
+ token="YOUR_TOKEN",
+ )
+
+
+ async def main() -> None:
+ await client.patch_v2vaults_id()
+
+
+ asyncio.run(main())
+ """
+ _response = await self._raw_client.patch_v2vaults_id(vault_id, request_options=request_options)
+ return _response.data
+
+ @property
+ def records(self):
+ if self._records is None:
+ from .records.client import AsyncRecordsClient # noqa: E402
+
+ self._records = AsyncRecordsClient(client_wrapper=self._client_wrapper)
+ return self._records
+
+ @property
+ def tokens(self):
+ if self._tokens is None:
+ from .tokens.client import AsyncTokensClient # noqa: E402
+
+ self._tokens = AsyncTokensClient(client_wrapper=self._client_wrapper)
+ return self._tokens
+
+ @property
+ def query(self):
+ if self._query is None:
+ from .query.client import AsyncQueryClient # noqa: E402
+
+ self._query = AsyncQueryClient(client_wrapper=self._client_wrapper)
+ return self._query
+
+ @property
+ def files(self):
+ if self._files is None:
+ from .files.client import AsyncFilesClient # noqa: E402
+
+ self._files = AsyncFilesClient(client_wrapper=self._client_wrapper)
+ return self._files
+
+
+def _get_base_url(*, base_url: typing.Optional[str] = None, environment: SkyflowAuthEnvironment) -> str:
if base_url is not None:
return base_url
elif environment is not None:
diff --git a/skyvault/skyflow/generated/rest/core/__init__.py b/skyvault/skyflow/generated/rest/core/__init__.py
index 31bbb818..5bc159a1 100644
--- a/skyvault/skyflow/generated/rest/core/__init__.py
+++ b/skyvault/skyflow/generated/rest/core/__init__.py
@@ -2,26 +2,91 @@
# isort: skip_file
-from .api_error import ApiError
-from .client_wrapper import AsyncClientWrapper, BaseClientWrapper, SyncClientWrapper
-from .datetime_utils import serialize_datetime
-from .file import File, convert_file_dict_to_httpx_tuples, with_content_type
-from .http_client import AsyncHttpClient, HttpClient
-from .http_response import AsyncHttpResponse, HttpResponse
-from .jsonable_encoder import jsonable_encoder
-from .pydantic_utilities import (
- IS_PYDANTIC_V2,
- UniversalBaseModel,
- UniversalRootModel,
- parse_obj_as,
- universal_field_validator,
- universal_root_validator,
- update_forward_refs,
-)
-from .query_encoder import encode_query
-from .remove_none_from_dict import remove_none_from_dict
-from .request_options import RequestOptions
-from .serialization import FieldMetadata, convert_and_respect_annotation_metadata
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .api_error import ApiError
+ from .client_wrapper import AsyncClientWrapper, BaseClientWrapper, SyncClientWrapper
+ from .datetime_utils import Rfc2822DateTime, parse_rfc2822_datetime, serialize_datetime
+ from .file import File, convert_file_dict_to_httpx_tuples, with_content_type
+ from .http_client import AsyncHttpClient, HttpClient
+ from .http_response import AsyncHttpResponse, HttpResponse
+ from .jsonable_encoder import encode_path_param, jsonable_encoder
+ from .logging import ConsoleLogger, ILogger, LogConfig, LogLevel, Logger, create_logger
+ from .parse_error import ParsingError
+ from .pydantic_utilities import (
+ IS_PYDANTIC_V2,
+ UniversalBaseModel,
+ UniversalRootModel,
+ parse_obj_as,
+ universal_field_validator,
+ universal_root_validator,
+ update_forward_refs,
+ )
+ from .query_encoder import encode_query
+ from .remove_none_from_dict import remove_none_from_dict
+ from .request_options import RequestOptions
+ from .serialization import FieldMetadata, convert_and_respect_annotation_metadata
+_dynamic_imports: typing.Dict[str, str] = {
+ "ApiError": ".api_error",
+ "AsyncClientWrapper": ".client_wrapper",
+ "AsyncHttpClient": ".http_client",
+ "AsyncHttpResponse": ".http_response",
+ "BaseClientWrapper": ".client_wrapper",
+ "ConsoleLogger": ".logging",
+ "FieldMetadata": ".serialization",
+ "File": ".file",
+ "HttpClient": ".http_client",
+ "HttpResponse": ".http_response",
+ "ILogger": ".logging",
+ "IS_PYDANTIC_V2": ".pydantic_utilities",
+ "LogConfig": ".logging",
+ "LogLevel": ".logging",
+ "Logger": ".logging",
+ "ParsingError": ".parse_error",
+ "RequestOptions": ".request_options",
+ "Rfc2822DateTime": ".datetime_utils",
+ "SyncClientWrapper": ".client_wrapper",
+ "UniversalBaseModel": ".pydantic_utilities",
+ "UniversalRootModel": ".pydantic_utilities",
+ "convert_and_respect_annotation_metadata": ".serialization",
+ "convert_file_dict_to_httpx_tuples": ".file",
+ "create_logger": ".logging",
+ "encode_path_param": ".jsonable_encoder",
+ "encode_query": ".query_encoder",
+ "jsonable_encoder": ".jsonable_encoder",
+ "parse_obj_as": ".pydantic_utilities",
+ "parse_rfc2822_datetime": ".datetime_utils",
+ "remove_none_from_dict": ".remove_none_from_dict",
+ "serialize_datetime": ".datetime_utils",
+ "universal_field_validator": ".pydantic_utilities",
+ "universal_root_validator": ".pydantic_utilities",
+ "update_forward_refs": ".pydantic_utilities",
+ "with_content_type": ".file",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
__all__ = [
"ApiError",
@@ -29,20 +94,30 @@
"AsyncHttpClient",
"AsyncHttpResponse",
"BaseClientWrapper",
+ "ConsoleLogger",
"FieldMetadata",
"File",
"HttpClient",
"HttpResponse",
+ "ILogger",
"IS_PYDANTIC_V2",
+ "LogConfig",
+ "LogLevel",
+ "Logger",
+ "ParsingError",
"RequestOptions",
+ "Rfc2822DateTime",
"SyncClientWrapper",
"UniversalBaseModel",
"UniversalRootModel",
"convert_and_respect_annotation_metadata",
"convert_file_dict_to_httpx_tuples",
+ "create_logger",
+ "encode_path_param",
"encode_query",
"jsonable_encoder",
"parse_obj_as",
+ "parse_rfc2822_datetime",
"remove_none_from_dict",
"serialize_datetime",
"universal_field_validator",
diff --git a/skyvault/skyflow/generated/rest/core/client_wrapper.py b/skyvault/skyflow/generated/rest/core/client_wrapper.py
index 355d775e..561d8aa6 100644
--- a/skyvault/skyflow/generated/rest/core/client_wrapper.py
+++ b/skyvault/skyflow/generated/rest/core/client_wrapper.py
@@ -4,6 +4,7 @@
import httpx
from .http_client import AsyncHttpClient, HttpClient
+from .logging import LogConfig, Logger
class BaseClientWrapper:
@@ -14,18 +15,29 @@ def __init__(
headers: typing.Optional[typing.Dict[str, str]] = None,
base_url: str,
timeout: typing.Optional[float] = None,
+ max_retries: int = 2,
+ stream_reconnection_enabled: typing.Optional[bool] = None,
+ max_stream_reconnection_attempts: typing.Optional[int] = None,
+ logging: typing.Optional[typing.Union[LogConfig, Logger]] = None,
):
self._token = token
self._headers = headers
self._base_url = base_url
self._timeout = timeout
+ self._max_retries = max_retries
+ self._stream_reconnection_enabled = stream_reconnection_enabled
+ self._max_stream_reconnection_attempts = max_stream_reconnection_attempts
+ self._logging = logging
def get_headers(self) -> typing.Dict[str, str]:
+ import platform
+
headers: typing.Dict[str, str] = {
- "User-Agent": "skyflow/1.16.1",
"X-Fern-Language": "Python",
- "X-Fern-SDK-Name": "skyflow",
- "X-Fern-SDK-Version": "1.16.1",
+ "X-Fern-Runtime": f"python/{platform.python_version()}",
+ "X-Fern-Platform": f"{platform.system().lower()}/{platform.release()}",
+ "X-Fern-SDK-Name": "skyflow.generated.rest",
+ "X-Fern-SDK-Version": "0.0.49",
**(self.get_custom_headers() or {}),
}
token = self._get_token()
@@ -48,6 +60,15 @@ def get_base_url(self) -> str:
def get_timeout(self) -> typing.Optional[float]:
return self._timeout
+ def get_max_retries(self) -> int:
+ return self._max_retries
+
+ def get_stream_reconnection_enabled(self) -> bool:
+ return self._stream_reconnection_enabled if self._stream_reconnection_enabled is not None else True
+
+ def get_max_stream_reconnection_attempts(self) -> typing.Optional[int]:
+ return self._max_stream_reconnection_attempts
+
class SyncClientWrapper(BaseClientWrapper):
def __init__(
@@ -57,14 +78,29 @@ def __init__(
headers: typing.Optional[typing.Dict[str, str]] = None,
base_url: str,
timeout: typing.Optional[float] = None,
+ max_retries: int = 2,
+ stream_reconnection_enabled: typing.Optional[bool] = None,
+ max_stream_reconnection_attempts: typing.Optional[int] = None,
+ logging: typing.Optional[typing.Union[LogConfig, Logger]] = None,
httpx_client: httpx.Client,
):
- super().__init__(token=token, headers=headers, base_url=base_url, timeout=timeout)
+ super().__init__(
+ token=token,
+ headers=headers,
+ base_url=base_url,
+ timeout=timeout,
+ max_retries=max_retries,
+ stream_reconnection_enabled=stream_reconnection_enabled,
+ max_stream_reconnection_attempts=max_stream_reconnection_attempts,
+ logging=logging,
+ )
self.httpx_client = HttpClient(
httpx_client=httpx_client,
base_headers=self.get_headers,
base_timeout=self.get_timeout,
base_url=self.get_base_url,
+ base_max_retries=self.get_max_retries(),
+ logging_config=self._logging,
)
@@ -76,12 +112,37 @@ def __init__(
headers: typing.Optional[typing.Dict[str, str]] = None,
base_url: str,
timeout: typing.Optional[float] = None,
+ max_retries: int = 2,
+ stream_reconnection_enabled: typing.Optional[bool] = None,
+ max_stream_reconnection_attempts: typing.Optional[int] = None,
+ logging: typing.Optional[typing.Union[LogConfig, Logger]] = None,
+ async_token: typing.Optional[typing.Callable[[], typing.Awaitable[str]]] = None,
httpx_client: httpx.AsyncClient,
):
- super().__init__(token=token, headers=headers, base_url=base_url, timeout=timeout)
+ super().__init__(
+ token=token,
+ headers=headers,
+ base_url=base_url,
+ timeout=timeout,
+ max_retries=max_retries,
+ stream_reconnection_enabled=stream_reconnection_enabled,
+ max_stream_reconnection_attempts=max_stream_reconnection_attempts,
+ logging=logging,
+ )
+ self._async_token = async_token
self.httpx_client = AsyncHttpClient(
httpx_client=httpx_client,
base_headers=self.get_headers,
base_timeout=self.get_timeout,
base_url=self.get_base_url,
+ base_max_retries=self.get_max_retries(),
+ async_base_headers=self.async_get_headers,
+ logging_config=self._logging,
)
+
+ async def async_get_headers(self) -> typing.Dict[str, str]:
+ headers = self.get_headers()
+ if self._async_token is not None:
+ token = await self._async_token()
+ headers["Authorization"] = f"Bearer {token}"
+ return headers
diff --git a/skyvault/skyflow/generated/rest/core/datetime_utils.py b/skyvault/skyflow/generated/rest/core/datetime_utils.py
index 7c9864a9..a12b2ad0 100644
--- a/skyvault/skyflow/generated/rest/core/datetime_utils.py
+++ b/skyvault/skyflow/generated/rest/core/datetime_utils.py
@@ -1,6 +1,48 @@
# This file was auto-generated by Fern from our API Definition.
import datetime as dt
+from email.utils import parsedate_to_datetime
+from typing import Any
+
+import pydantic
+
+IS_PYDANTIC_V2 = pydantic.VERSION.startswith("2.")
+
+
+def parse_rfc2822_datetime(v: Any) -> dt.datetime:
+ """
+ Parse an RFC 2822 datetime string (e.g., "Wed, 02 Oct 2002 13:00:00 GMT")
+ into a datetime object. If the value is already a datetime, return it as-is.
+ Falls back to ISO 8601 parsing if RFC 2822 parsing fails.
+ """
+ if isinstance(v, dt.datetime):
+ return v
+ if isinstance(v, str):
+ try:
+ return parsedate_to_datetime(v)
+ except Exception:
+ pass
+ # Fallback to ISO 8601 parsing
+ return dt.datetime.fromisoformat(v.replace("Z", "+00:00"))
+ raise ValueError(f"Expected str or datetime, got {type(v)}")
+
+
+class Rfc2822DateTime(dt.datetime):
+ """A datetime subclass that parses RFC 2822 date strings.
+
+ On Pydantic V1, uses __get_validators__ for pre-validation.
+ On Pydantic V2, uses __get_pydantic_core_schema__ for BeforeValidator-style parsing.
+ """
+
+ @classmethod
+ def __get_validators__(cls): # type: ignore[no-untyped-def]
+ yield parse_rfc2822_datetime
+
+ @classmethod
+ def __get_pydantic_core_schema__(cls, _source_type: Any, _handler: Any) -> Any: # type: ignore[override]
+ from pydantic_core import core_schema
+
+ return core_schema.no_info_before_validator_function(parse_rfc2822_datetime, core_schema.datetime_schema())
def serialize_datetime(v: dt.datetime) -> str:
diff --git a/skyvault/skyflow/generated/rest/core/force_multipart.py b/skyvault/skyflow/generated/rest/core/force_multipart.py
index ae24ccff..5440913f 100644
--- a/skyvault/skyflow/generated/rest/core/force_multipart.py
+++ b/skyvault/skyflow/generated/rest/core/force_multipart.py
@@ -1,7 +1,9 @@
# This file was auto-generated by Fern from our API Definition.
+from typing import Any, Dict
-class ForceMultipartDict(dict):
+
+class ForceMultipartDict(Dict[str, Any]):
"""
A dictionary subclass that always evaluates to True in boolean contexts.
@@ -9,7 +11,7 @@ class ForceMultipartDict(dict):
the dictionary is empty, which would normally evaluate to False.
"""
- def __bool__(self):
+ def __bool__(self) -> bool:
return True
diff --git a/skyvault/skyflow/generated/rest/core/http_client.py b/skyvault/skyflow/generated/rest/core/http_client.py
index e4173f99..3e5a7865 100644
--- a/skyvault/skyflow/generated/rest/core/http_client.py
+++ b/skyvault/skyflow/generated/rest/core/http_client.py
@@ -3,9 +3,9 @@
import asyncio
import email.utils
import re
+import socket
import time
import typing
-import urllib.parse
from contextlib import asynccontextmanager, contextmanager
from random import random
@@ -13,14 +13,48 @@
from .file import File, convert_file_dict_to_httpx_tuples
from .force_multipart import FORCE_MULTIPART
from .jsonable_encoder import jsonable_encoder
+from .logging import LogConfig, Logger, create_logger
from .query_encoder import encode_query
-from .remove_none_from_dict import remove_none_from_dict
+from .remove_none_from_dict import remove_none_from_dict as remove_none_from_dict
from .request_options import RequestOptions
from httpx._types import RequestFiles
-INITIAL_RETRY_DELAY_SECONDS = 0.5
-MAX_RETRY_DELAY_SECONDS = 10
-MAX_RETRY_DELAY_SECONDS_FROM_HEADER = 30
+INITIAL_RETRY_DELAY_SECONDS = 1.0
+MAX_RETRY_DELAY_SECONDS = 60.0
+JITTER_FACTOR = 0.2 # 20% random jitter
+
+
+def get_keepalive_socket_options(
+ idle: int = 60,
+ intvl: int = 30,
+ cnt: int = 5,
+) -> typing.List[typing.Tuple[int, int, int]]:
+ """
+ Build TCP keepalive socket options for the current platform.
+
+ Keepalive probes keep otherwise-idle connections alive so that long,
+ non-streaming requests survive idle-connection reaping by a firewall,
+ load balancer, or NAT. The available socket constants are OS-dependent,
+ so each option is guarded and only emitted when the platform defines it:
+
+ - ``SO_KEEPALIVE`` is portable (Linux/macOS/Windows).
+ - The idle-before-first-probe knob is ``TCP_KEEPIDLE`` on Linux and modern
+ Windows, but ``TCP_KEEPALIVE`` on macOS.
+ - ``TCP_KEEPINTVL`` / ``TCP_KEEPCNT`` exist on Linux/macOS/modern Windows.
+
+ Passing these tuples to ``httpx.HTTPTransport(socket_options=...)`` /
+ ``httpx.AsyncHTTPTransport(socket_options=...)`` applies them to every
+ connection the transport opens.
+ """
+ opts: typing.List[typing.Tuple[int, int, int]] = [(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)]
+ idle_const = getattr(socket, "TCP_KEEPIDLE", None) or getattr(socket, "TCP_KEEPALIVE", None)
+ if idle_const:
+ opts.append((socket.IPPROTO_TCP, idle_const, idle))
+ if hasattr(socket, "TCP_KEEPINTVL"):
+ opts.append((socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, intvl))
+ if hasattr(socket, "TCP_KEEPCNT"):
+ opts.append((socket.IPPROTO_TCP, socket.TCP_KEEPCNT, cnt))
+ return opts
def _parse_retry_after(response_headers: httpx.Headers) -> typing.Optional[float]:
@@ -64,6 +98,38 @@ def _parse_retry_after(response_headers: httpx.Headers) -> typing.Optional[float
return seconds
+def _add_positive_jitter(delay: float) -> float:
+ """Add positive jitter (0-20%) to prevent thundering herd."""
+ jitter_multiplier = 1 + random() * JITTER_FACTOR
+ return delay * jitter_multiplier
+
+
+def _add_symmetric_jitter(delay: float) -> float:
+ """Add symmetric jitter (±10%) for exponential backoff."""
+ jitter_multiplier = 1 + (random() - 0.5) * JITTER_FACTOR
+ return delay * jitter_multiplier
+
+
+def _parse_x_ratelimit_reset(response_headers: httpx.Headers) -> typing.Optional[float]:
+ """
+ Parse the X-RateLimit-Reset header (Unix timestamp in seconds).
+ Returns seconds to wait, or None if header is missing/invalid.
+ """
+ reset_time_str = response_headers.get("x-ratelimit-reset")
+ if reset_time_str is None:
+ return None
+
+ try:
+ reset_time = int(reset_time_str)
+ delay = reset_time - time.time()
+ if delay > 0:
+ return delay
+ except (ValueError, TypeError):
+ pass
+
+ return None
+
+
def _retry_timeout(response: httpx.Response, retries: int) -> float:
"""
Determine the amount of time to wait before retrying a request.
@@ -71,22 +137,94 @@ def _retry_timeout(response: httpx.Response, retries: int) -> float:
with a jitter to determine the number of seconds to wait.
"""
- # If the API asks us to wait a certain amount of time (and it's a reasonable amount), just do what it says.
+ # 1. Check Retry-After header first
retry_after = _parse_retry_after(response.headers)
- if retry_after is not None and retry_after <= MAX_RETRY_DELAY_SECONDS_FROM_HEADER:
- return retry_after
+ if retry_after is not None and retry_after > 0:
+ return min(retry_after, MAX_RETRY_DELAY_SECONDS)
+
+ # 2. Check X-RateLimit-Reset header (with positive jitter)
+ ratelimit_reset = _parse_x_ratelimit_reset(response.headers)
+ if ratelimit_reset is not None:
+ return _add_positive_jitter(min(ratelimit_reset, MAX_RETRY_DELAY_SECONDS))
- # Apply exponential backoff, capped at MAX_RETRY_DELAY_SECONDS.
- retry_delay = min(INITIAL_RETRY_DELAY_SECONDS * pow(2.0, retries), MAX_RETRY_DELAY_SECONDS)
+ # 3. Fall back to exponential backoff (with symmetric jitter)
+ backoff = min(INITIAL_RETRY_DELAY_SECONDS * pow(2.0, retries), MAX_RETRY_DELAY_SECONDS)
+ return _add_symmetric_jitter(backoff)
- # Add a randomness / jitter to the retry delay to avoid overwhelming the server with retries.
- timeout = retry_delay * (1 - 0.25 * random())
- return timeout if timeout >= 0 else 0
+
+def _retry_timeout_from_retries(retries: int) -> float:
+ """Determine retry timeout using exponential backoff when no response is available."""
+ backoff = min(INITIAL_RETRY_DELAY_SECONDS * pow(2.0, retries), MAX_RETRY_DELAY_SECONDS)
+ return _add_symmetric_jitter(backoff)
def _should_retry(response: httpx.Response) -> bool:
- retryable_400s = [429, 408, 409]
- return response.status_code >= 500 or response.status_code in retryable_400s
+ return response.status_code >= 500 or response.status_code in [429, 408, 409]
+
+
+_SENSITIVE_HEADERS = frozenset(
+ {
+ "authorization",
+ "www-authenticate",
+ "x-api-key",
+ "api-key",
+ "apikey",
+ "x-api-token",
+ "x-auth-token",
+ "auth-token",
+ "cookie",
+ "set-cookie",
+ "proxy-authorization",
+ "proxy-authenticate",
+ "x-csrf-token",
+ "x-xsrf-token",
+ "x-session-token",
+ "x-access-token",
+ }
+)
+
+
+def _redact_headers(headers: typing.Dict[str, str]) -> typing.Dict[str, str]:
+ return {k: ("[REDACTED]" if k.lower() in _SENSITIVE_HEADERS else v) for k, v in headers.items()}
+
+
+def _build_url(base_url: str, path: typing.Optional[str]) -> str:
+ """
+ Build a full URL by joining a base URL with a path.
+
+ This function correctly handles base URLs that contain path prefixes (e.g., tenant-based URLs)
+ by using string concatenation instead of urllib.parse.urljoin(), which would incorrectly
+ strip path components when the path starts with '/'.
+
+ Example:
+ >>> _build_url("https://cloud.example.com/org/tenant/api", "/users")
+ 'https://cloud.example.com/org/tenant/api/users'
+
+ Args:
+ base_url: The base URL, which may contain path prefixes.
+ path: The path to append. Can be None or empty string.
+
+ Returns:
+ The full URL with base_url and path properly joined.
+ """
+ if not path:
+ return base_url
+ return f"{base_url.rstrip('/')}/{path.lstrip('/')}"
+
+
+def _maybe_filter_none_from_multipart_data(
+ data: typing.Optional[typing.Any],
+ request_files: typing.Optional[RequestFiles],
+ force_multipart: typing.Optional[bool],
+) -> typing.Optional[typing.Any]:
+ """
+ Filter None values from data body for multipart/form requests.
+ This prevents httpx from converting None to empty strings in multipart encoding.
+ Only applies when files are present or force_multipart is True.
+ """
+ if data is not None and isinstance(data, typing.Mapping) and (request_files or force_multipart):
+ return remove_none_from_dict(data)
+ return data
def remove_omit_from_dict(
@@ -134,7 +272,16 @@ def get_request_body(
data: typing.Optional[typing.Any],
request_options: typing.Optional[RequestOptions],
omit: typing.Optional[typing.Any],
+ optional_body: bool = False,
) -> typing.Tuple[typing.Optional[typing.Any], typing.Optional[typing.Any]]:
+ # A whole body left at the sentinel was never passed by the caller, so it is absent
+ # rather than empty: the request carries no content and no `Content-Type`.
+ if omit is not None:
+ if json is omit:
+ json = None
+ if data is omit:
+ data = None
+
json_body = None
data_body = None
if data is not None:
@@ -143,8 +290,41 @@ def get_request_body(
# If both data and json are None, we send json data in the event extra properties are specified
json_body = maybe_filter_request_body(json, request_options, omit)
- # If you have an empty JSON body, you should just send None
- return (json_body if json_body != {} else None), data_body if data_body != {} else None
+ has_additional_body_parameters = bool(
+ request_options is not None and request_options.get("additional_body_parameters")
+ )
+
+ # Only collapse empty dict to None when the body was not explicitly provided
+ # and there are no additional body parameters. This preserves explicit empty
+ # bodies (e.g., when an endpoint has a request body type but all fields are optional).
+ # `optional_body` marks an endpoint whose body the API does not require, where a body
+ # that ends up empty means the caller passed none of its properties, so the request is
+ # sent with no content and no `Content-Type`.
+ if json_body == {} and (json is None or optional_body) and not has_additional_body_parameters:
+ json_body = None
+ if data_body == {} and (data is None or optional_body) and not has_additional_body_parameters:
+ data_body = None
+
+ return json_body, data_body
+
+
+def drop_content_type_without_body(
+ headers: typing.Dict[str, typing.Any],
+ *,
+ json_body: typing.Optional[typing.Any],
+ data_body: typing.Optional[typing.Any],
+ optional_body: bool,
+) -> typing.Dict[str, typing.Any]:
+ """Strip ``Content-Type`` from a request that carries no body.
+
+ ``get_request_body`` drops the body of an ``optional_body`` endpoint when the caller
+ supplied none of it, but the endpoint still passes the content type it would have used.
+ A request that sends nothing must not advertise a media type, so a server that branches
+ on the header sees a bodyless call for what it is.
+ """
+ if not optional_body or json_body is not None or data_body is not None:
+ return headers
+ return {key: value for key, value in headers.items() if key.lower() != "content-type"}
class HttpClient:
@@ -155,11 +335,15 @@ def __init__(
base_timeout: typing.Callable[[], typing.Optional[float]],
base_headers: typing.Callable[[], typing.Dict[str, str]],
base_url: typing.Optional[typing.Callable[[], str]] = None,
+ base_max_retries: int = 2,
+ logging_config: typing.Optional[typing.Union[LogConfig, Logger]] = None,
):
self.base_url = base_url
self.base_timeout = base_timeout
self.base_headers = base_headers
+ self.base_max_retries = base_max_retries
self.httpx_client = httpx_client
+ self.logger = create_logger(logging_config)
def get_base_url(self, maybe_base_url: typing.Optional[str]) -> str:
base_url = maybe_base_url
@@ -188,18 +372,24 @@ def request(
] = None,
headers: typing.Optional[typing.Dict[str, typing.Any]] = None,
request_options: typing.Optional[RequestOptions] = None,
- retries: int = 2,
+ retries: int = 0,
omit: typing.Optional[typing.Any] = None,
+ optional_body: bool = False,
force_multipart: typing.Optional[bool] = None,
) -> httpx.Response:
base_url = self.get_base_url(base_url)
- timeout = (
- request_options.get("timeout_in_seconds")
+ _timeout = (
+ request_options.get("timeout")
+ if request_options is not None and request_options.get("timeout") is not None
+ else request_options.get("timeout_in_seconds")
if request_options is not None and request_options.get("timeout_in_seconds") is not None
else self.base_timeout()
)
+ timeout = _timeout if _timeout is not None else httpx.USE_CLIENT_DEFAULT
- json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit)
+ json_body, data_body = get_request_body(
+ json=json, data=data, request_options=request_options, omit=omit, optional_body=optional_body
+ )
request_files: typing.Optional[RequestFiles] = (
convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit))
@@ -210,45 +400,91 @@ def request(
if (request_files is None or len(request_files) == 0) and force_multipart:
request_files = FORCE_MULTIPART
- response = self.httpx_client.request(
- method=method,
- url=urllib.parse.urljoin(f"{base_url}/", path),
- headers=jsonable_encoder(
+ data_body = _maybe_filter_none_from_multipart_data(data_body, request_files, force_multipart)
+
+ # Compute encoded params separately to avoid passing empty list to httpx
+ # (httpx strips existing query params from URL when params=[] is passed)
+ _encoded_params = encode_query(
+ jsonable_encoder(
remove_none_from_dict(
- {
- **self.base_headers(),
- **(headers if headers is not None else {}),
- **(request_options.get("additional_headers", {}) or {} if request_options is not None else {}),
- }
- )
- ),
- params=encode_query(
- jsonable_encoder(
- remove_none_from_dict(
- remove_omit_from_dict(
- {
- **(params if params is not None else {}),
- **(
- request_options.get("additional_query_parameters", {}) or {}
- if request_options is not None
- else {}
- ),
- },
- omit,
- )
+ remove_omit_from_dict(
+ {
+ **(params if params is not None else {}),
+ **(
+ request_options.get("additional_query_parameters", {}) or {}
+ if request_options is not None
+ else {}
+ ),
+ },
+ omit,
)
)
- ),
- json=json_body,
- data=data_body,
- content=content,
- files=request_files,
- timeout=timeout,
+ )
+ )
+
+ _request_url = _build_url(base_url, path)
+ _request_headers = jsonable_encoder(
+ remove_none_from_dict(
+ {
+ **self.base_headers(),
+ **(headers if headers is not None else {}),
+ **(request_options.get("additional_headers", {}) or {} if request_options is not None else {}),
+ }
+ )
+ )
+ _request_headers = drop_content_type_without_body(
+ _request_headers, json_body=json_body, data_body=data_body, optional_body=optional_body
+ )
+
+ if self.logger.is_debug():
+ self.logger.debug(
+ "Making HTTP request",
+ method=method,
+ url=_request_url,
+ headers=_redact_headers(_request_headers),
+ has_body=json_body is not None or data_body is not None,
+ )
+
+ max_retries: int = (
+ request_options.get("max_retries", self.base_max_retries)
+ if request_options is not None
+ else self.base_max_retries
)
- max_retries: int = request_options.get("max_retries", 0) if request_options is not None else 0
+ try:
+ response = self.httpx_client.request(
+ method=method,
+ url=_request_url,
+ headers=_request_headers,
+ params=_encoded_params if _encoded_params else None,
+ json=json_body,
+ data=data_body,
+ content=content,
+ files=request_files,
+ timeout=timeout,
+ )
+ except (httpx.ConnectError, httpx.RemoteProtocolError):
+ if retries < max_retries:
+ time.sleep(_retry_timeout_from_retries(retries=retries))
+ return self.request(
+ path=path,
+ method=method,
+ base_url=base_url,
+ params=params,
+ json=json,
+ data=data,
+ content=content,
+ files=files,
+ headers=headers,
+ request_options=request_options,
+ retries=retries + 1,
+ omit=omit,
+ force_multipart=force_multipart,
+ )
+ raise
+
if _should_retry(response=response):
- if max_retries > retries:
+ if retries < max_retries:
time.sleep(_retry_timeout(response=response, retries=retries))
return self.request(
path=path,
@@ -256,12 +492,32 @@ def request(
base_url=base_url,
params=params,
json=json,
+ data=data,
content=content,
files=files,
headers=headers,
request_options=request_options,
retries=retries + 1,
omit=omit,
+ force_multipart=force_multipart,
+ )
+
+ if self.logger.is_debug():
+ if 200 <= response.status_code < 400:
+ self.logger.debug(
+ "HTTP request succeeded",
+ method=method,
+ url=_request_url,
+ status_code=response.status_code,
+ )
+
+ if self.logger.is_error():
+ if response.status_code >= 400:
+ self.logger.error(
+ "HTTP request failed with error status",
+ method=method,
+ url=_request_url,
+ status_code=response.status_code,
)
return response
@@ -285,16 +541,20 @@ def stream(
] = None,
headers: typing.Optional[typing.Dict[str, typing.Any]] = None,
request_options: typing.Optional[RequestOptions] = None,
- retries: int = 2,
+ retries: int = 0,
omit: typing.Optional[typing.Any] = None,
+ optional_body: bool = False,
force_multipart: typing.Optional[bool] = None,
) -> typing.Iterator[httpx.Response]:
base_url = self.get_base_url(base_url)
- timeout = (
- request_options.get("timeout_in_seconds")
+ _timeout = (
+ request_options.get("timeout")
+ if request_options is not None and request_options.get("timeout") is not None
+ else request_options.get("timeout_in_seconds")
if request_options is not None and request_options.get("timeout_in_seconds") is not None
else self.base_timeout()
)
+ timeout = _timeout if _timeout is not None else httpx.USE_CLIENT_DEFAULT
request_files: typing.Optional[RequestFiles] = (
convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit))
@@ -305,37 +565,59 @@ def stream(
if (request_files is None or len(request_files) == 0) and force_multipart:
request_files = FORCE_MULTIPART
- json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit)
+ json_body, data_body = get_request_body(
+ json=json, data=data, request_options=request_options, omit=omit, optional_body=optional_body
+ )
+
+ data_body = _maybe_filter_none_from_multipart_data(data_body, request_files, force_multipart)
- with self.httpx_client.stream(
- method=method,
- url=urllib.parse.urljoin(f"{base_url}/", path),
- headers=jsonable_encoder(
+ # Compute encoded params separately to avoid passing empty list to httpx
+ # (httpx strips existing query params from URL when params=[] is passed)
+ _encoded_params = encode_query(
+ jsonable_encoder(
remove_none_from_dict(
- {
- **self.base_headers(),
- **(headers if headers is not None else {}),
- **(request_options.get("additional_headers", {}) if request_options is not None else {}),
- }
- )
- ),
- params=encode_query(
- jsonable_encoder(
- remove_none_from_dict(
- remove_omit_from_dict(
- {
- **(params if params is not None else {}),
- **(
- request_options.get("additional_query_parameters", {})
- if request_options is not None
- else {}
- ),
- },
- omit,
- )
+ remove_omit_from_dict(
+ {
+ **(params if params is not None else {}),
+ **(
+ request_options.get("additional_query_parameters", {})
+ if request_options is not None
+ else {}
+ ),
+ },
+ omit,
)
)
- ),
+ )
+ )
+
+ _request_url = _build_url(base_url, path)
+ _request_headers = jsonable_encoder(
+ remove_none_from_dict(
+ {
+ **self.base_headers(),
+ **(headers if headers is not None else {}),
+ **(request_options.get("additional_headers", {}) if request_options is not None else {}),
+ }
+ )
+ )
+ _request_headers = drop_content_type_without_body(
+ _request_headers, json_body=json_body, data_body=data_body, optional_body=optional_body
+ )
+
+ if self.logger.is_debug():
+ self.logger.debug(
+ "Making streaming HTTP request",
+ method=method,
+ url=_request_url,
+ headers=_redact_headers(_request_headers),
+ )
+
+ with self.httpx_client.stream(
+ method=method,
+ url=_request_url,
+ headers=_request_headers,
+ params=_encoded_params if _encoded_params else None,
json=json_body,
data=data_body,
content=content,
@@ -353,11 +635,22 @@ def __init__(
base_timeout: typing.Callable[[], typing.Optional[float]],
base_headers: typing.Callable[[], typing.Dict[str, str]],
base_url: typing.Optional[typing.Callable[[], str]] = None,
+ base_max_retries: int = 2,
+ async_base_headers: typing.Optional[typing.Callable[[], typing.Awaitable[typing.Dict[str, str]]]] = None,
+ logging_config: typing.Optional[typing.Union[LogConfig, Logger]] = None,
):
self.base_url = base_url
self.base_timeout = base_timeout
self.base_headers = base_headers
+ self.base_max_retries = base_max_retries
+ self.async_base_headers = async_base_headers
self.httpx_client = httpx_client
+ self.logger = create_logger(logging_config)
+
+ async def _get_headers(self) -> typing.Dict[str, str]:
+ if self.async_base_headers is not None:
+ return await self.async_base_headers()
+ return self.base_headers()
def get_base_url(self, maybe_base_url: typing.Optional[str]) -> str:
base_url = maybe_base_url
@@ -386,16 +679,20 @@ async def request(
] = None,
headers: typing.Optional[typing.Dict[str, typing.Any]] = None,
request_options: typing.Optional[RequestOptions] = None,
- retries: int = 2,
+ retries: int = 0,
omit: typing.Optional[typing.Any] = None,
+ optional_body: bool = False,
force_multipart: typing.Optional[bool] = None,
) -> httpx.Response:
base_url = self.get_base_url(base_url)
- timeout = (
- request_options.get("timeout_in_seconds")
+ _timeout = (
+ request_options.get("timeout")
+ if request_options is not None and request_options.get("timeout") is not None
+ else request_options.get("timeout_in_seconds")
if request_options is not None and request_options.get("timeout_in_seconds") is not None
else self.base_timeout()
)
+ timeout = _timeout if _timeout is not None else httpx.USE_CLIENT_DEFAULT
request_files: typing.Optional[RequestFiles] = (
convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit))
@@ -406,48 +703,98 @@ async def request(
if (request_files is None or len(request_files) == 0) and force_multipart:
request_files = FORCE_MULTIPART
- json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit)
+ json_body, data_body = get_request_body(
+ json=json, data=data, request_options=request_options, omit=omit, optional_body=optional_body
+ )
- # Add the input to each of these and do None-safety checks
- response = await self.httpx_client.request(
- method=method,
- url=urllib.parse.urljoin(f"{base_url}/", path),
- headers=jsonable_encoder(
+ data_body = _maybe_filter_none_from_multipart_data(data_body, request_files, force_multipart)
+
+ # Get headers (supports async token providers)
+ _headers = await self._get_headers()
+
+ # Compute encoded params separately to avoid passing empty list to httpx
+ # (httpx strips existing query params from URL when params=[] is passed)
+ _encoded_params = encode_query(
+ jsonable_encoder(
remove_none_from_dict(
- {
- **self.base_headers(),
- **(headers if headers is not None else {}),
- **(request_options.get("additional_headers", {}) or {} if request_options is not None else {}),
- }
- )
- ),
- params=encode_query(
- jsonable_encoder(
- remove_none_from_dict(
- remove_omit_from_dict(
- {
- **(params if params is not None else {}),
- **(
- request_options.get("additional_query_parameters", {}) or {}
- if request_options is not None
- else {}
- ),
- },
- omit,
- )
+ remove_omit_from_dict(
+ {
+ **(params if params is not None else {}),
+ **(
+ request_options.get("additional_query_parameters", {}) or {}
+ if request_options is not None
+ else {}
+ ),
+ },
+ omit,
)
)
- ),
- json=json_body,
- data=data_body,
- content=content,
- files=request_files,
- timeout=timeout,
+ )
+ )
+
+ _request_url = _build_url(base_url, path)
+ _request_headers = jsonable_encoder(
+ remove_none_from_dict(
+ {
+ **_headers,
+ **(headers if headers is not None else {}),
+ **(request_options.get("additional_headers", {}) or {} if request_options is not None else {}),
+ }
+ )
+ )
+ _request_headers = drop_content_type_without_body(
+ _request_headers, json_body=json_body, data_body=data_body, optional_body=optional_body
+ )
+
+ if self.logger.is_debug():
+ self.logger.debug(
+ "Making HTTP request",
+ method=method,
+ url=_request_url,
+ headers=_redact_headers(_request_headers),
+ has_body=json_body is not None or data_body is not None,
+ )
+
+ max_retries: int = (
+ request_options.get("max_retries", self.base_max_retries)
+ if request_options is not None
+ else self.base_max_retries
)
- max_retries: int = request_options.get("max_retries", 0) if request_options is not None else 0
+ try:
+ response = await self.httpx_client.request(
+ method=method,
+ url=_request_url,
+ headers=_request_headers,
+ params=_encoded_params if _encoded_params else None,
+ json=json_body,
+ data=data_body,
+ content=content,
+ files=request_files,
+ timeout=timeout,
+ )
+ except (httpx.ConnectError, httpx.RemoteProtocolError):
+ if retries < max_retries:
+ await asyncio.sleep(_retry_timeout_from_retries(retries=retries))
+ return await self.request(
+ path=path,
+ method=method,
+ base_url=base_url,
+ params=params,
+ json=json,
+ data=data,
+ content=content,
+ files=files,
+ headers=headers,
+ request_options=request_options,
+ retries=retries + 1,
+ omit=omit,
+ force_multipart=force_multipart,
+ )
+ raise
+
if _should_retry(response=response):
- if max_retries > retries:
+ if retries < max_retries:
await asyncio.sleep(_retry_timeout(response=response, retries=retries))
return await self.request(
path=path,
@@ -455,13 +802,34 @@ async def request(
base_url=base_url,
params=params,
json=json,
+ data=data,
content=content,
files=files,
headers=headers,
request_options=request_options,
retries=retries + 1,
omit=omit,
+ force_multipart=force_multipart,
+ )
+
+ if self.logger.is_debug():
+ if 200 <= response.status_code < 400:
+ self.logger.debug(
+ "HTTP request succeeded",
+ method=method,
+ url=_request_url,
+ status_code=response.status_code,
+ )
+
+ if self.logger.is_error():
+ if response.status_code >= 400:
+ self.logger.error(
+ "HTTP request failed with error status",
+ method=method,
+ url=_request_url,
+ status_code=response.status_code,
)
+
return response
@asynccontextmanager
@@ -483,16 +851,20 @@ async def stream(
] = None,
headers: typing.Optional[typing.Dict[str, typing.Any]] = None,
request_options: typing.Optional[RequestOptions] = None,
- retries: int = 2,
+ retries: int = 0,
omit: typing.Optional[typing.Any] = None,
+ optional_body: bool = False,
force_multipart: typing.Optional[bool] = None,
) -> typing.AsyncIterator[httpx.Response]:
base_url = self.get_base_url(base_url)
- timeout = (
- request_options.get("timeout_in_seconds")
+ _timeout = (
+ request_options.get("timeout")
+ if request_options is not None and request_options.get("timeout") is not None
+ else request_options.get("timeout_in_seconds")
if request_options is not None and request_options.get("timeout_in_seconds") is not None
else self.base_timeout()
)
+ timeout = _timeout if _timeout is not None else httpx.USE_CLIENT_DEFAULT
request_files: typing.Optional[RequestFiles] = (
convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit))
@@ -503,37 +875,62 @@ async def stream(
if (request_files is None or len(request_files) == 0) and force_multipart:
request_files = FORCE_MULTIPART
- json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit)
+ json_body, data_body = get_request_body(
+ json=json, data=data, request_options=request_options, omit=omit, optional_body=optional_body
+ )
- async with self.httpx_client.stream(
- method=method,
- url=urllib.parse.urljoin(f"{base_url}/", path),
- headers=jsonable_encoder(
+ data_body = _maybe_filter_none_from_multipart_data(data_body, request_files, force_multipart)
+
+ # Get headers (supports async token providers)
+ _headers = await self._get_headers()
+
+ # Compute encoded params separately to avoid passing empty list to httpx
+ # (httpx strips existing query params from URL when params=[] is passed)
+ _encoded_params = encode_query(
+ jsonable_encoder(
remove_none_from_dict(
- {
- **self.base_headers(),
- **(headers if headers is not None else {}),
- **(request_options.get("additional_headers", {}) if request_options is not None else {}),
- }
- )
- ),
- params=encode_query(
- jsonable_encoder(
- remove_none_from_dict(
- remove_omit_from_dict(
- {
- **(params if params is not None else {}),
- **(
- request_options.get("additional_query_parameters", {})
- if request_options is not None
- else {}
- ),
- },
- omit=omit,
- )
+ remove_omit_from_dict(
+ {
+ **(params if params is not None else {}),
+ **(
+ request_options.get("additional_query_parameters", {})
+ if request_options is not None
+ else {}
+ ),
+ },
+ omit=omit,
)
)
- ),
+ )
+ )
+
+ _request_url = _build_url(base_url, path)
+ _request_headers = jsonable_encoder(
+ remove_none_from_dict(
+ {
+ **_headers,
+ **(headers if headers is not None else {}),
+ **(request_options.get("additional_headers", {}) if request_options is not None else {}),
+ }
+ )
+ )
+ _request_headers = drop_content_type_without_body(
+ _request_headers, json_body=json_body, data_body=data_body, optional_body=optional_body
+ )
+
+ if self.logger.is_debug():
+ self.logger.debug(
+ "Making streaming HTTP request",
+ method=method,
+ url=_request_url,
+ headers=_redact_headers(_request_headers),
+ )
+
+ async with self.httpx_client.stream(
+ method=method,
+ url=_request_url,
+ headers=_request_headers,
+ params=_encoded_params if _encoded_params else None,
json=json_body,
data=data_body,
content=content,
diff --git a/skyvault/skyflow/generated/rest/core/http_response.py b/skyvault/skyflow/generated/rest/core/http_response.py
index 48a1798a..9aa1e188 100644
--- a/skyvault/skyflow/generated/rest/core/http_response.py
+++ b/skyvault/skyflow/generated/rest/core/http_response.py
@@ -4,12 +4,12 @@
import httpx
+# Generic to represent the underlying type of the data wrapped by the HTTP response.
T = TypeVar("T")
-"""Generic to represent the underlying type of the data wrapped by the HTTP response."""
class BaseHttpResponse:
- """Minimalist HTTP response wrapper that exposes response headers."""
+ """Minimalist HTTP response wrapper that exposes response headers and status code."""
_response: httpx.Response
@@ -20,6 +20,14 @@ def __init__(self, response: httpx.Response):
def headers(self) -> Dict[str, str]:
return dict(self._response.headers)
+ @property
+ def status_code(self) -> int:
+ return self._response.status_code
+
+ @property
+ def response(self) -> httpx.Response:
+ return self._response
+
class HttpResponse(Generic[T], BaseHttpResponse):
"""HTTP response wrapper that exposes response headers and data."""
diff --git a/skyvault/skyflow/generated/rest/core/http_sse/__init__.py b/skyvault/skyflow/generated/rest/core/http_sse/__init__.py
new file mode 100644
index 00000000..730e5a33
--- /dev/null
+++ b/skyvault/skyflow/generated/rest/core/http_sse/__init__.py
@@ -0,0 +1,42 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from ._api import EventSource, aconnect_sse, connect_sse
+ from ._exceptions import SSEError
+ from ._models import ServerSentEvent
+_dynamic_imports: typing.Dict[str, str] = {
+ "EventSource": "._api",
+ "SSEError": "._exceptions",
+ "ServerSentEvent": "._models",
+ "aconnect_sse": "._api",
+ "connect_sse": "._api",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = ["EventSource", "SSEError", "ServerSentEvent", "aconnect_sse", "connect_sse"]
diff --git a/skyvault/skyflow/generated/rest/core/http_sse/_api.py b/skyvault/skyflow/generated/rest/core/http_sse/_api.py
new file mode 100644
index 00000000..9ca5602c
--- /dev/null
+++ b/skyvault/skyflow/generated/rest/core/http_sse/_api.py
@@ -0,0 +1,455 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import codecs
+import re
+import time
+from contextlib import asynccontextmanager, contextmanager
+from typing import (
+ Any,
+ AsyncContextManager,
+ AsyncGenerator,
+ AsyncIterator,
+ Callable,
+ ContextManager,
+ Iterator,
+ Optional,
+)
+
+import anyio
+import httpx
+from ._decoders import SSEDecoder
+from ._exceptions import SSEError
+from ._models import ServerSentEvent
+
+MAX_LINE_SIZE: int = 1_048_576 # 1 MiB
+
+# Reconnection defaults, mirroring the TypeScript SDK's Stream implementation.
+DEFAULT_MAX_RECONNECTION_ATTEMPTS: int = 5
+DEFAULT_RECONNECT_DELAY_MS: int = 1_000
+MAX_RECONNECT_DELAY_MS: int = 30_000
+
+
+# A reconnect callback re-issues the original request (with a ``Last-Event-ID``
+# header set to the supplied event id) and returns a *context manager* yielding
+# a fresh streaming ``httpx.Response``. Sync clients supply a sync context
+# manager; async clients supply an async one.
+class EventSource:
+ def __init__(
+ self,
+ response: httpx.Response,
+ *,
+ resumable: bool = False,
+ stream_reconnection_enabled: bool = True,
+ max_stream_reconnection_attempts: Optional[int] = None,
+ stream_terminator: Optional[str] = None,
+ reconnect: Optional[Callable[[str], Any]] = None,
+ ) -> None:
+ self._response = response
+ self._resumable = resumable
+ self._stream_reconnection_enabled = stream_reconnection_enabled
+ self._max_stream_reconnection_attempts = max_stream_reconnection_attempts
+ self._stream_terminator = stream_terminator
+ self._reconnect = reconnect
+
+ @staticmethod
+ def _is_event_stream(response: httpx.Response) -> bool:
+ content_type = response.headers.get("content-type", "").partition(";")[0]
+ return "text/event-stream" in content_type
+
+ def _check_content_type(self) -> None:
+ if not self._is_event_stream(self._response):
+ content_type = self._response.headers.get("content-type", "").partition(";")[0]
+ raise SSEError(
+ f"Expected response header Content-Type to contain 'text/event-stream', got {content_type!r}"
+ )
+
+ def _is_reconnect_response_usable(self, response: httpx.Response) -> bool:
+ """Whether a reconnected response can be resumed as an SSE stream.
+
+ ``httpx.stream`` does not raise on non-success status, so a resume that
+ returns an error page (e.g. ``200 text/html`` or a ``500`` body) would
+ otherwise be parsed as SSE and yield garbage/zero events. Such a
+ response is treated as a failed attempt (back off and retry) instead.
+ """
+ return response.status_code < 400 and self._is_event_stream(response)
+
+ def _get_charset(self, response: Optional[httpx.Response] = None) -> str:
+ """Extract charset from Content-Type header, fallback to UTF-8."""
+ resolved = response if response is not None else self._response
+ content_type = resolved.headers.get("content-type", "")
+
+ # Parse charset parameter using regex
+ charset_match = re.search(r"charset=([^;\s]+)", content_type, re.IGNORECASE)
+ if charset_match:
+ charset = charset_match.group(1).strip("\"'")
+ # Validate that it's a known encoding
+ try:
+ # Test if the charset is valid by trying to encode/decode
+ "test".encode(charset).decode(charset)
+ return charset
+ except (LookupError, UnicodeError):
+ # If charset is invalid, fall back to UTF-8
+ pass
+
+ # Default to UTF-8 if no charset specified or invalid charset
+ return "utf-8"
+
+ @property
+ def response(self) -> httpx.Response:
+ return self._response
+
+ @staticmethod
+ def _normalize_sse_line_endings(buf: str) -> str:
+ """Normalize line endings per the SSE spec (\\r\\n → \\n, bare \\r → \\n).
+
+ A trailing \\r is preserved because it may pair with a leading \\n in
+ the next chunk to form a single \\r\\n terminator.
+ """
+ buf = buf.replace("\r\n", "\n")
+ if buf.endswith("\r"):
+ return buf[:-1].replace("\r", "\n") + "\r"
+ return buf.replace("\r", "\n")
+
+ def _new_text_decoder(self, response: Optional[httpx.Response] = None) -> "codecs.IncrementalDecoder":
+ return codecs.getincrementaldecoder(self._get_charset(response))(errors="replace")
+
+ def _reconnect_applicable(self) -> bool:
+ """Whether reconnection is configured for this stream at all.
+
+ This is the terminator-gating half of the reconnect decision, kept
+ separate from :meth:`_should_reconnect` (which additionally requires a
+ last *dispatched* id and an unexhausted attempt budget). The split lets
+ a mid-stream transport error terminate consistently:
+ - a stream that can never reconnect (non-resumable, no terminator,
+ disabled, or no callback) must re-raise the error to the caller, so a
+ truncated stream is not mistaken for a clean completion;
+ - a resumable stream that has merely run out of attempts (or has no id
+ to resume from) ends cleanly — the same way an exhausted empty/error
+ -body resume already does, matching the TypeScript ``return``.
+ """
+ return (
+ self._resumable
+ and self._stream_terminator is not None
+ and self._stream_reconnection_enabled
+ and self._reconnect is not None
+ )
+
+ def _should_reconnect(self, last_dispatched_id: Optional[str], reconnect_attempts: int) -> bool:
+ """Decide whether a prematurely-ended stream should be reconnected.
+
+ Mirrors the TypeScript ``shouldReconnect`` gating:
+ - only resumable SSE endpoints with a configured terminator, reconnect
+ enabled, and a reconnect callback are eligible (see
+ :meth:`_reconnect_applicable`);
+ - a last *dispatched* event id must exist to resume from;
+ - the consecutive-failed-attempt cap must not be exceeded.
+ """
+ if not self._reconnect_applicable():
+ return False
+ if not last_dispatched_id:
+ return False
+ max_attempts = (
+ self._max_stream_reconnection_attempts
+ if self._max_stream_reconnection_attempts is not None
+ else DEFAULT_MAX_RECONNECTION_ATTEMPTS
+ )
+ if reconnect_attempts >= max_attempts:
+ return False
+ return True
+
+ def _reconnect_delay_seconds(self, last_retry: Optional[int]) -> float:
+ """Backoff before a reconnect.
+
+ Uses the server's most recent ``retry:`` directive (milliseconds) when
+ present, otherwise a default of ``DEFAULT_RECONNECT_DELAY_MS``, clamped
+ to ``MAX_RECONNECT_DELAY_MS``.
+ """
+ base_ms = last_retry if (last_retry is not None and last_retry > 0) else DEFAULT_RECONNECT_DELAY_MS
+ return min(base_ms, MAX_RECONNECT_DELAY_MS) / 1000.0
+
+ def _sleep_before_reconnect(self, last_retry: Optional[int]) -> None:
+ # ``time.sleep`` blocks the calling thread but remains interruptible by
+ # signals (e.g. ``KeyboardInterrupt``), which propagate out and abort
+ # the reconnect without issuing another request.
+ time.sleep(self._reconnect_delay_seconds(last_retry))
+
+ async def _asleep_before_reconnect(self, last_retry: Optional[int]) -> None:
+ # ``anyio.sleep`` is cancellation-aware: if the consumer cancels the task
+ # or closes the async generator mid-delay, this raises (and no further
+ # request is issued) instead of blocking for the whole interval.
+ await anyio.sleep(self._reconnect_delay_seconds(last_retry))
+
+ def _decode_response(
+ self,
+ response: httpx.Response,
+ decoder: SSEDecoder,
+ text_decoder: "codecs.IncrementalDecoder",
+ ) -> Iterator[ServerSentEvent]:
+ buf = ""
+ for chunk in response.iter_bytes():
+ buf += text_decoder.decode(chunk)
+ buf = self._normalize_sse_line_endings(buf)
+
+ while "\n" in buf:
+ line, buf = buf.split("\n", 1)
+ sse = decoder.decode(line)
+ if sse is not None:
+ yield sse
+
+ if len(buf) > MAX_LINE_SIZE:
+ raise SSEError(
+ f"SSE line exceeded maximum size of {MAX_LINE_SIZE} characters without encountering a newline"
+ )
+
+ yield from self._flush_decoder(buf, decoder, text_decoder)
+
+ async def _adecode_response(
+ self,
+ response: httpx.Response,
+ decoder: SSEDecoder,
+ text_decoder: "codecs.IncrementalDecoder",
+ ) -> AsyncGenerator[ServerSentEvent, None]:
+ buf = ""
+ async for chunk in response.aiter_bytes():
+ buf += text_decoder.decode(chunk)
+ buf = self._normalize_sse_line_endings(buf)
+
+ while "\n" in buf:
+ line, buf = buf.split("\n", 1)
+ sse = decoder.decode(line)
+ if sse is not None:
+ yield sse
+
+ if len(buf) > MAX_LINE_SIZE:
+ raise SSEError(
+ f"SSE line exceeded maximum size of {MAX_LINE_SIZE} characters without encountering a newline"
+ )
+
+ for sse in self._flush_decoder(buf, decoder, text_decoder):
+ yield sse
+
+ def _flush_decoder(
+ self,
+ buf: str,
+ decoder: SSEDecoder,
+ text_decoder: "codecs.IncrementalDecoder",
+ ) -> Iterator[ServerSentEvent]:
+ # Flush any remaining bytes from the incremental decoder
+ buf += text_decoder.decode(b"", final=True)
+ buf = buf.replace("\r\n", "\n").replace("\r", "\n")
+
+ if len(buf) > MAX_LINE_SIZE:
+ raise SSEError(
+ f"SSE line exceeded maximum size of {MAX_LINE_SIZE} characters without encountering a newline"
+ )
+
+ while "\n" in buf:
+ line, buf = buf.split("\n", 1)
+ sse = decoder.decode(line)
+ if sse is not None:
+ yield sse
+
+ if buf.strip():
+ sse = decoder.decode(buf)
+ if sse is not None:
+ yield sse
+
+ def iter_sse(self) -> Iterator[ServerSentEvent]:
+ self._check_content_type()
+ decoder = SSEDecoder()
+ text_decoder = self._new_text_decoder()
+
+ last_dispatched_id: Optional[str] = None
+ last_retry: Optional[int] = None
+ # Consecutive failed reconnection attempts. Reset to 0 whenever an event
+ # is successfully dispatched (reset-on-progress) — matching browser
+ # `EventSource` semantics: a server that emits >=1 event then drops on
+ # every connection can reconnect indefinitely.
+ reconnect_attempts = 0
+
+ # ``None`` means there is no live stream to read this iteration (e.g. a
+ # failed reconnect); the loop then re-evaluates the reconnect decision
+ # without re-reading an exhausted response.
+ response: Optional[httpx.Response] = self._response
+ # Context manager for a response we opened ourselves and must close.
+ # The initial response is owned by the caller, so it starts as None.
+ owned_cm: Optional[ContextManager[httpx.Response]] = None
+ try:
+ while True:
+ if response is not None:
+ events = self._decode_response(response, decoder, text_decoder)
+ while True:
+ try:
+ sse = next(events)
+ except StopIteration:
+ break
+ except SSEError:
+ # A protocol violation (e.g. an oversized line) is a
+ # genuine error, not a dropped connection; propagate it.
+ # Listed first because ``SSEError`` subclasses
+ # ``httpx.TransportError``.
+ raise
+ except httpx.TransportError:
+ # A transport error mid-stream (e.g. the server dropped
+ # the connection: ``ReadError``/``RemoteProtocolError``)
+ # is a premature end. Only swallow it when reconnection
+ # is configured for this stream; otherwise re-raise so a
+ # non-resumable stream still surfaces the error to the
+ # caller instead of looking like a clean completion.
+ # When reconnection is applicable but the attempt budget
+ # is exhausted, we ``break`` and end cleanly below — the
+ # same way an exhausted empty/error-body resume does, so
+ # give-up is consistent regardless of failure shape.
+ # ``next`` is used rather than ``for`` so this cannot
+ # swallow a ``GeneratorExit`` raised at a ``yield``.
+ if not self._reconnect_applicable():
+ raise
+ break
+ yield sse
+ if sse.id:
+ last_dispatched_id = sse.id
+ if sse.retry is not None:
+ last_retry = sse.retry
+ reconnect_attempts = 0
+
+ if not self._should_reconnect(last_dispatched_id, reconnect_attempts):
+ return
+ reconnect_attempts += 1
+
+ self._sleep_before_reconnect(last_retry)
+
+ # Close the previously-opened reconnect response before opening
+ # a new one so we never hold more than one extra connection.
+ if owned_cm is not None:
+ owned_cm.__exit__(None, None, None)
+ owned_cm = None
+
+ assert self._reconnect is not None # guaranteed by _should_reconnect
+ try:
+ cm: ContextManager[httpx.Response] = self._reconnect(last_dispatched_id or "")
+ new_response = cm.__enter__()
+ except Exception:
+ # A failed reconnect consumes an attempt; back off and retry.
+ response = None
+ continue
+ owned_cm = cm
+ if new_response is None or not self._is_reconnect_response_usable(new_response):
+ # Null/empty body or a non-SSE/error response (e.g. 204/304,
+ # a 500, or an HTML error page): treat as a failed attempt.
+ response = None
+ continue
+
+ response = new_response
+ # Drop any partial event left over from the dropped stream, but
+ # keep the last event id (per the SSE spec) and start a fresh
+ # incremental text decoder for the new connection.
+ decoder.reset_in_progress_event()
+ text_decoder = self._new_text_decoder(new_response)
+ finally:
+ if owned_cm is not None:
+ owned_cm.__exit__(None, None, None)
+
+ async def aiter_sse(self) -> AsyncGenerator[ServerSentEvent, None]:
+ self._check_content_type()
+ decoder = SSEDecoder()
+ text_decoder = self._new_text_decoder()
+
+ last_dispatched_id: Optional[str] = None
+ last_retry: Optional[int] = None
+ reconnect_attempts = 0
+
+ response: Optional[httpx.Response] = self._response
+ owned_cm: Optional[AsyncContextManager[httpx.Response]] = None
+ try:
+ while True:
+ if response is not None:
+ events = self._adecode_response(response, decoder, text_decoder)
+ while True:
+ try:
+ sse = await events.__anext__()
+ except StopAsyncIteration:
+ break
+ except SSEError:
+ # A protocol violation (e.g. an oversized line) is a
+ # genuine error, not a dropped connection; propagate it.
+ # Listed first because ``SSEError`` subclasses
+ # ``httpx.TransportError``.
+ raise
+ except httpx.TransportError:
+ # A transport error mid-stream (e.g. the server dropped
+ # the connection: ``ReadError``/``RemoteProtocolError``)
+ # is a premature end. Only swallow it when reconnection
+ # is configured for this stream; otherwise re-raise so a
+ # non-resumable stream still surfaces the error to the
+ # caller instead of looking like a clean completion.
+ # When reconnection is applicable but the attempt budget
+ # is exhausted, we ``break`` and end cleanly below — the
+ # same way an exhausted empty/error-body resume does, so
+ # give-up is consistent regardless of failure shape.
+ if not self._reconnect_applicable():
+ raise
+ break
+ yield sse
+ if sse.id:
+ last_dispatched_id = sse.id
+ if sse.retry is not None:
+ last_retry = sse.retry
+ reconnect_attempts = 0
+
+ if not self._should_reconnect(last_dispatched_id, reconnect_attempts):
+ return
+ reconnect_attempts += 1
+
+ await self._asleep_before_reconnect(last_retry)
+
+ if owned_cm is not None:
+ await owned_cm.__aexit__(None, None, None)
+ owned_cm = None
+
+ assert self._reconnect is not None # guaranteed by _should_reconnect
+ try:
+ cm: AsyncContextManager[httpx.Response] = self._reconnect(last_dispatched_id or "")
+ new_response = await cm.__aenter__()
+ except Exception:
+ response = None
+ continue
+ owned_cm = cm
+ if new_response is None or not self._is_reconnect_response_usable(new_response):
+ response = None
+ continue
+
+ response = new_response
+ decoder.reset_in_progress_event()
+ text_decoder = self._new_text_decoder(new_response)
+ finally:
+ if owned_cm is not None:
+ # Shield the close so a cancellation delivered while reading a
+ # reconnected response still fully tears the connection down
+ # instead of leaking it until the client is closed.
+ with anyio.CancelScope(shield=True):
+ await owned_cm.__aexit__(None, None, None)
+
+
+@contextmanager
+def connect_sse(client: httpx.Client, method: str, url: str, **kwargs: Any) -> Iterator[EventSource]:
+ headers = kwargs.pop("headers", {})
+ headers["Accept"] = "text/event-stream"
+ headers["Cache-Control"] = "no-store"
+
+ with client.stream(method, url, headers=headers, **kwargs) as response:
+ yield EventSource(response)
+
+
+@asynccontextmanager
+async def aconnect_sse(
+ client: httpx.AsyncClient,
+ method: str,
+ url: str,
+ **kwargs: Any,
+) -> AsyncIterator[EventSource]:
+ headers = kwargs.pop("headers", {})
+ headers["Accept"] = "text/event-stream"
+ headers["Cache-Control"] = "no-store"
+
+ async with client.stream(method, url, headers=headers, **kwargs) as response:
+ yield EventSource(response)
diff --git a/skyvault/skyflow/generated/rest/core/http_sse/_decoders.py b/skyvault/skyflow/generated/rest/core/http_sse/_decoders.py
new file mode 100644
index 00000000..1f6b35ec
--- /dev/null
+++ b/skyvault/skyflow/generated/rest/core/http_sse/_decoders.py
@@ -0,0 +1,74 @@
+# This file was auto-generated by Fern from our API Definition.
+
+from typing import List, Optional
+
+from ._models import ServerSentEvent
+
+
+class SSEDecoder:
+ def __init__(self) -> None:
+ self._event = ""
+ self._data: List[str] = []
+ self._last_event_id = ""
+ self._retry: Optional[int] = None
+
+ def reset_in_progress_event(self) -> None:
+ """Discard any partially-parsed (undispatched) event.
+
+ Used when a stream ends mid-event before reconnecting: the buffered
+ ``event``/``data``/``retry`` fields of the never-dispatched event must
+ be dropped so they do not corrupt the first event of the reconnected
+ stream. Per the SSE spec the last event id is *not* reset here — it
+ persists across connections.
+ """
+ self._event = ""
+ self._data = []
+ self._retry = None
+
+ def decode(self, line: str) -> Optional[ServerSentEvent]:
+ # See: https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation # noqa: E501
+
+ if not line:
+ if not self._event and not self._data and not self._last_event_id and self._retry is None:
+ return None
+
+ sse = ServerSentEvent(
+ event=self._event,
+ data="\n".join(self._data),
+ id=self._last_event_id,
+ retry=self._retry,
+ )
+
+ # NOTE: as per the SSE spec, do not reset last_event_id.
+ self._event = ""
+ self._data = []
+ self._retry = None
+
+ return sse
+
+ if line.startswith(":"):
+ return None
+
+ fieldname, _, value = line.partition(":")
+
+ if value.startswith(" "):
+ value = value[1:]
+
+ if fieldname == "event":
+ self._event = value
+ elif fieldname == "data":
+ self._data.append(value)
+ elif fieldname == "id":
+ if "\0" in value:
+ pass
+ else:
+ self._last_event_id = value
+ elif fieldname == "retry":
+ try:
+ self._retry = int(value)
+ except (TypeError, ValueError):
+ pass
+ else:
+ pass # Field is ignored.
+
+ return None
diff --git a/skyvault/skyflow/generated/rest/types/uuid_.py b/skyvault/skyflow/generated/rest/core/http_sse/_exceptions.py
similarity index 51%
rename from skyvault/skyflow/generated/rest/types/uuid_.py
rename to skyvault/skyflow/generated/rest/core/http_sse/_exceptions.py
index cf319b43..81605a8a 100644
--- a/skyvault/skyflow/generated/rest/types/uuid_.py
+++ b/skyvault/skyflow/generated/rest/core/http_sse/_exceptions.py
@@ -1,3 +1,7 @@
# This file was auto-generated by Fern from our API Definition.
-Uuid = str
+import httpx
+
+
+class SSEError(httpx.TransportError):
+ pass
diff --git a/skyvault/skyflow/generated/rest/core/http_sse/_models.py b/skyvault/skyflow/generated/rest/core/http_sse/_models.py
new file mode 100644
index 00000000..1af57f8f
--- /dev/null
+++ b/skyvault/skyflow/generated/rest/core/http_sse/_models.py
@@ -0,0 +1,17 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import json
+from dataclasses import dataclass
+from typing import Any, Optional
+
+
+@dataclass(frozen=True)
+class ServerSentEvent:
+ event: str = "message"
+ data: str = ""
+ id: str = ""
+ retry: Optional[int] = None
+
+ def json(self) -> Any:
+ """Parse the data field as JSON."""
+ return json.loads(self.data)
diff --git a/skyvault/skyflow/generated/rest/core/jsonable_encoder.py b/skyvault/skyflow/generated/rest/core/jsonable_encoder.py
index afee3662..f638cc9a 100644
--- a/skyvault/skyflow/generated/rest/core/jsonable_encoder.py
+++ b/skyvault/skyflow/generated/rest/core/jsonable_encoder.py
@@ -15,6 +15,7 @@
from pathlib import PurePath
from types import GeneratorType
from typing import Any, Callable, Dict, List, Optional, Set, Union
+from urllib.parse import quote
import pydantic
from .datetime_utils import serialize_datetime
@@ -30,6 +31,10 @@
def jsonable_encoder(obj: Any, custom_encoder: Optional[Dict[Any, Callable[[Any], Any]]] = None) -> Any:
custom_encoder = custom_encoder or {}
+ # Generated SDKs use Ellipsis (`...`) as the sentinel value for "OMIT".
+ # OMIT values should be excluded from serialized payloads.
+ if obj is Ellipsis:
+ return None
if custom_encoder:
if type(obj) in custom_encoder:
return custom_encoder[type(obj)](obj)
@@ -70,6 +75,8 @@ def jsonable_encoder(obj: Any, custom_encoder: Optional[Dict[Any, Callable[[Any]
allowed_keys = set(obj.keys())
for key, value in obj.items():
if key in allowed_keys:
+ if value is Ellipsis:
+ continue
encoded_key = jsonable_encoder(key, custom_encoder=custom_encoder)
encoded_value = jsonable_encoder(value, custom_encoder=custom_encoder)
encoded_dict[encoded_key] = encoded_value
@@ -77,6 +84,8 @@ def jsonable_encoder(obj: Any, custom_encoder: Optional[Dict[Any, Callable[[Any]
if isinstance(obj, (list, set, frozenset, GeneratorType, tuple)):
encoded_list = []
for item in obj:
+ if item is Ellipsis:
+ continue
encoded_list.append(jsonable_encoder(item, custom_encoder=custom_encoder))
return encoded_list
@@ -98,3 +107,27 @@ def fallback_serializer(o: Any) -> Any:
return jsonable_encoder(data, custom_encoder=custom_encoder)
return to_jsonable_with_fallback(obj, fallback_serializer)
+
+
+def encode_path_param(obj: Any) -> str:
+ """Encode a value for use in a URL path segment.
+
+ Ensures proper string conversion for all types, including
+ booleans which need lowercase 'true'/'false' rather than
+ Python's 'True'/'False'.
+ """
+ if isinstance(obj, bool):
+ return "true" if obj else "false"
+ return str(jsonable_encoder(obj))
+
+
+def quote_path_param(obj: Any) -> str:
+ """Encode a value for use in a URL path segment, percent-encoding it.
+
+ Same as encode_path_param, except the result is percent-encoded so
+ that a value containing "/" or ".." cannot change which endpoint
+ the request resolves to.
+ """
+ if isinstance(obj, bool):
+ return "true" if obj else "false"
+ return quote(str(jsonable_encoder(obj)), safe="")
diff --git a/skyvault/skyflow/generated/rest/core/logging.py b/skyvault/skyflow/generated/rest/core/logging.py
new file mode 100644
index 00000000..e5e57245
--- /dev/null
+++ b/skyvault/skyflow/generated/rest/core/logging.py
@@ -0,0 +1,107 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import logging
+import typing
+
+LogLevel = typing.Literal["debug", "info", "warn", "error"]
+
+_LOG_LEVEL_MAP: typing.Dict[LogLevel, int] = {
+ "debug": 1,
+ "info": 2,
+ "warn": 3,
+ "error": 4,
+}
+
+
+class ILogger(typing.Protocol):
+ def debug(self, message: str, **kwargs: typing.Any) -> None: ...
+ def info(self, message: str, **kwargs: typing.Any) -> None: ...
+ def warn(self, message: str, **kwargs: typing.Any) -> None: ...
+ def error(self, message: str, **kwargs: typing.Any) -> None: ...
+
+
+class ConsoleLogger:
+ _logger: logging.Logger
+
+ def __init__(self) -> None:
+ self._logger = logging.getLogger("fern")
+ if not self._logger.handlers:
+ handler = logging.StreamHandler()
+ handler.setFormatter(logging.Formatter("%(levelname)s - %(message)s"))
+ self._logger.addHandler(handler)
+ self._logger.setLevel(logging.DEBUG)
+
+ def debug(self, message: str, **kwargs: typing.Any) -> None:
+ self._logger.debug(message, extra=kwargs)
+
+ def info(self, message: str, **kwargs: typing.Any) -> None:
+ self._logger.info(message, extra=kwargs)
+
+ def warn(self, message: str, **kwargs: typing.Any) -> None:
+ self._logger.warning(message, extra=kwargs)
+
+ def error(self, message: str, **kwargs: typing.Any) -> None:
+ self._logger.error(message, extra=kwargs)
+
+
+class LogConfig(typing.TypedDict, total=False):
+ level: LogLevel
+ logger: ILogger
+ silent: bool
+
+
+class Logger:
+ _level: int
+ _logger: ILogger
+ _silent: bool
+
+ def __init__(self, *, level: LogLevel, logger: ILogger, silent: bool) -> None:
+ self._level = _LOG_LEVEL_MAP[level]
+ self._logger = logger
+ self._silent = silent
+
+ def _should_log(self, level: LogLevel) -> bool:
+ return not self._silent and self._level <= _LOG_LEVEL_MAP[level]
+
+ def is_debug(self) -> bool:
+ return self._should_log("debug")
+
+ def is_info(self) -> bool:
+ return self._should_log("info")
+
+ def is_warn(self) -> bool:
+ return self._should_log("warn")
+
+ def is_error(self) -> bool:
+ return self._should_log("error")
+
+ def debug(self, message: str, **kwargs: typing.Any) -> None:
+ if self.is_debug():
+ self._logger.debug(message, **kwargs)
+
+ def info(self, message: str, **kwargs: typing.Any) -> None:
+ if self.is_info():
+ self._logger.info(message, **kwargs)
+
+ def warn(self, message: str, **kwargs: typing.Any) -> None:
+ if self.is_warn():
+ self._logger.warn(message, **kwargs)
+
+ def error(self, message: str, **kwargs: typing.Any) -> None:
+ if self.is_error():
+ self._logger.error(message, **kwargs)
+
+
+_default_logger: Logger = Logger(level="info", logger=ConsoleLogger(), silent=True)
+
+
+def create_logger(config: typing.Optional[typing.Union[LogConfig, Logger]] = None) -> Logger:
+ if config is None:
+ return _default_logger
+ if isinstance(config, Logger):
+ return config
+ return Logger(
+ level=config.get("level", "info"),
+ logger=config.get("logger", ConsoleLogger()),
+ silent=config.get("silent", True),
+ )
diff --git a/skyvault/skyflow/generated/rest/core/parse_error.py b/skyvault/skyflow/generated/rest/core/parse_error.py
new file mode 100644
index 00000000..4527c6a8
--- /dev/null
+++ b/skyvault/skyflow/generated/rest/core/parse_error.py
@@ -0,0 +1,36 @@
+# This file was auto-generated by Fern from our API Definition.
+
+from typing import Any, Dict, Optional
+
+
+class ParsingError(Exception):
+ """
+ Raised when the SDK fails to parse/validate a response from the server.
+ This typically indicates that the server returned a response whose shape
+ does not match the expected schema.
+ """
+
+ headers: Optional[Dict[str, str]]
+ status_code: Optional[int]
+ body: Any
+ cause: Optional[Exception]
+
+ def __init__(
+ self,
+ *,
+ headers: Optional[Dict[str, str]] = None,
+ status_code: Optional[int] = None,
+ body: Any = None,
+ cause: Optional[Exception] = None,
+ ) -> None:
+ self.headers = headers
+ self.status_code = status_code
+ self.body = body
+ self.cause = cause
+ super().__init__()
+ if cause is not None:
+ self.__cause__ = cause
+
+ def __str__(self) -> str:
+ cause_str = f", cause: {self.cause}" if self.cause is not None else ""
+ return f"headers: {self.headers}, status_code: {self.status_code}, body: {self.body}{cause_str}"
diff --git a/skyvault/skyflow/generated/rest/core/pydantic_utilities.py b/skyvault/skyflow/generated/rest/core/pydantic_utilities.py
index 7db29500..70816b99 100644
--- a/skyvault/skyflow/generated/rest/core/pydantic_utilities.py
+++ b/skyvault/skyflow/generated/rest/core/pydantic_utilities.py
@@ -2,30 +2,130 @@
# nopycln: file
import datetime as dt
+import inspect
+import json
+import logging
+import weakref
from collections import defaultdict
-from typing import Any, Callable, ClassVar, Dict, List, Mapping, Optional, Set, Tuple, Type, TypeVar, Union, cast
+from dataclasses import asdict
+from typing import (
+ TYPE_CHECKING,
+ Any,
+ Callable,
+ ClassVar,
+ Dict,
+ List,
+ Mapping,
+ Optional,
+ Set,
+ Tuple,
+ Type,
+ TypeVar,
+ Union,
+ cast,
+)
import pydantic
+import typing_extensions
+from pydantic.fields import FieldInfo as _FieldInfo
+
+_logger = logging.getLogger(__name__)
+
+if TYPE_CHECKING:
+ from .http_sse._models import ServerSentEvent
IS_PYDANTIC_V2 = pydantic.VERSION.startswith("2.")
if IS_PYDANTIC_V2:
- from pydantic.v1.datetime_parse import parse_date as parse_date
- from pydantic.v1.datetime_parse import parse_datetime as parse_datetime
- from pydantic.v1.fields import ModelField as ModelField
- from pydantic.v1.json import ENCODERS_BY_TYPE as encoders_by_type # type: ignore[attr-defined]
- from pydantic.v1.typing import get_args as get_args
- from pydantic.v1.typing import get_origin as get_origin
- from pydantic.v1.typing import is_literal_type as is_literal_type
- from pydantic.v1.typing import is_union as is_union
+ _datetime_adapter = pydantic.TypeAdapter(dt.datetime) # type: ignore[attr-defined]
+ _date_adapter = pydantic.TypeAdapter(dt.date) # type: ignore[attr-defined]
+
+ def parse_datetime(value: Any) -> dt.datetime: # type: ignore[misc]
+ if isinstance(value, dt.datetime):
+ return value
+ return _datetime_adapter.validate_python(value)
+
+ def parse_date(value: Any) -> dt.date: # type: ignore[misc]
+ if isinstance(value, dt.datetime):
+ return value.date()
+ if isinstance(value, dt.date):
+ return value
+ return _date_adapter.validate_python(value)
+
+ # Avoid importing from pydantic.v1 to maintain Python 3.14 compatibility.
+ from typing import get_args as get_args # type: ignore[assignment]
+ from typing import get_origin as get_origin # type: ignore[assignment]
+
+ def is_literal_type(tp: Optional[Type[Any]]) -> bool: # type: ignore[misc]
+ return typing_extensions.get_origin(tp) is typing_extensions.Literal
+
+ def is_union(tp: Optional[Type[Any]]) -> bool: # type: ignore[misc]
+ return tp is Union or typing_extensions.get_origin(tp) is Union # type: ignore[comparison-overlap]
+
+ # Inline encoders_by_type to avoid importing from pydantic.v1.json
+ import re as _re
+ from collections import deque as _deque
+ from decimal import Decimal as _Decimal
+ from enum import Enum as _Enum
+ from ipaddress import (
+ IPv4Address as _IPv4Address,
+ )
+ from ipaddress import (
+ IPv4Interface as _IPv4Interface,
+ )
+ from ipaddress import (
+ IPv4Network as _IPv4Network,
+ )
+ from ipaddress import (
+ IPv6Address as _IPv6Address,
+ )
+ from ipaddress import (
+ IPv6Interface as _IPv6Interface,
+ )
+ from ipaddress import (
+ IPv6Network as _IPv6Network,
+ )
+ from pathlib import Path as _Path
+ from types import GeneratorType as _GeneratorType
+ from uuid import UUID as _UUID
+
+ from pydantic.fields import FieldInfo as ModelField # type: ignore[no-redef, assignment]
+
+ def _decimal_encoder(dec_value: Any) -> Any:
+ if dec_value.as_tuple().exponent >= 0:
+ return int(dec_value)
+ return float(dec_value)
+
+ encoders_by_type: Dict[Type[Any], Callable[[Any], Any]] = { # type: ignore[no-redef]
+ bytes: lambda o: o.decode(),
+ dt.date: lambda o: o.isoformat(),
+ dt.datetime: lambda o: o.isoformat(),
+ dt.time: lambda o: o.isoformat(),
+ dt.timedelta: lambda td: td.total_seconds(),
+ _Decimal: _decimal_encoder,
+ _Enum: lambda o: o.value,
+ frozenset: list,
+ _deque: list,
+ _GeneratorType: list,
+ _IPv4Address: str,
+ _IPv4Interface: str,
+ _IPv4Network: str,
+ _IPv6Address: str,
+ _IPv6Interface: str,
+ _IPv6Network: str,
+ _Path: str,
+ _re.Pattern: lambda o: o.pattern,
+ set: list,
+ _UUID: str,
+ }
else:
from pydantic.datetime_parse import parse_date as parse_date # type: ignore[no-redef]
from pydantic.datetime_parse import parse_datetime as parse_datetime # type: ignore[no-redef]
- from pydantic.fields import ModelField as ModelField # type: ignore[attr-defined, no-redef]
+ from pydantic.fields import ModelField as ModelField # type: ignore[attr-defined, no-redef, assignment]
from pydantic.json import ENCODERS_BY_TYPE as encoders_by_type # type: ignore[no-redef]
from pydantic.typing import get_args as get_args # type: ignore[no-redef]
from pydantic.typing import get_origin as get_origin # type: ignore[no-redef]
- from pydantic.typing import is_literal_type as is_literal_type # type: ignore[no-redef]
+ from pydantic.typing import is_literal_type as is_literal_type # type: ignore[no-redef, assignment]
from pydantic.typing import is_union as is_union # type: ignore[no-redef]
from .datetime_utils import serialize_datetime
@@ -36,11 +136,128 @@
Model = TypeVar("Model", bound=pydantic.BaseModel)
+def parse_sse_obj(sse: "ServerSentEvent", type_: Type[T]) -> T:
+ """
+ Parse a ServerSentEvent into the appropriate type.
+
+ This function handles data-level discrimination where the discriminator
+ (e.g., 'type') is inside the 'data' payload. It parses the SSE data field
+ as JSON and deserializes it into the target type.
+
+ Note: Protocol-level discrimination (where the discriminator comes from
+ the SSE event: field) is handled at code-generation time and does not
+ use this function.
+
+ Args:
+ sse: The ServerSentEvent object to parse
+ type_: The target type to deserialize into
+
+ Returns:
+ The parsed object of type T
+
+ Note:
+ This function is only available in SDK contexts where http_sse module exists.
+ """
+ sse_event = asdict(sse)
+ data_value = sse_event.get("data")
+ if isinstance(data_value, str) and data_value:
+ try:
+ parsed_data = json.loads(data_value)
+ return parse_obj_as(type_, parsed_data)
+ except json.JSONDecodeError as e:
+ _logger.warning(
+ "Failed to parse SSE data field as JSON: %s, data: %s",
+ e,
+ data_value[:100] if len(data_value) > 100 else data_value,
+ )
+ return parse_obj_as(type_, sse_event)
+
+
+_type_adapter_cache: Dict[int, Any] = {}
+
+
+def _get_type_adapter(type_: Type[Any]) -> Any:
+ key = id(type_)
+ adapter = _type_adapter_cache.get(key)
+ if adapter is None:
+ adapter = pydantic.TypeAdapter(type_) # type: ignore[attr-defined]
+ _type_adapter_cache[key] = adapter
+ return adapter
+
+
+_field_alias_cache: "weakref.WeakKeyDictionary[type, Tuple[Dict[str, str], Tuple[str, ...]]]" = (
+ weakref.WeakKeyDictionary()
+)
+
+
+def _get_field_aliases(model: type) -> Tuple[Dict[str, str], Tuple[str, ...]]:
+ """
+ Map of field name to Pydantic alias for the fields whose alias differs from their name, together with the
+ keys that are ambiguous (an alias of one field and the name of another). Computed once per model class.
+ """
+ cached = _field_alias_cache.get(model)
+ if cached is None:
+ fields: Mapping[str, Any] = (
+ getattr(model, "model_fields", {}) if IS_PYDANTIC_V2 else getattr(model, "__fields__", {})
+ )
+ name_to_alias: Dict[str, str] = {}
+ for name, field in fields.items():
+ alias = getattr(field, "alias", None)
+ if alias is not None and alias != name:
+ name_to_alias[name] = alias
+ cached = (name_to_alias, tuple(alias for alias in name_to_alias.values() if alias in fields))
+ _field_alias_cache[model] = cached
+ return cached
+
+
+def _coerce_keys_to_aliases(model: type, data: Any) -> Any:
+ """
+ Accept Python field names in input by rewriting them to their Pydantic aliases,
+ while avoiding silent collisions when a key could refer to multiple fields.
+ """
+ if not isinstance(data, Mapping):
+ return data
+
+ name_to_alias, ambiguous_keys = _get_field_aliases(model)
+ for key in ambiguous_keys:
+ if key in data and name_to_alias.get(key, key) not in data:
+ raise ValueError(
+ f"Ambiguous input key '{key}': it is both a field name and an alias. "
+ "Provide the explicit alias key to disambiguate."
+ )
+
+ if not name_to_alias or not any(name in data for name in name_to_alias):
+ return data if isinstance(data, dict) else dict(data)
+
+ rewritten: Dict[str, Any] = dict(data)
+ for name, alias in name_to_alias.items():
+ if name in data and alias not in rewritten:
+ rewritten[alias] = rewritten.pop(name)
+
+ return rewritten
+
+
def parse_obj_as(type_: Type[T], object_: Any) -> T:
- dealiased_object = convert_and_respect_annotation_metadata(object_=object_, annotation=type_, direction="read")
+ # convert_and_respect_annotation_metadata is required for TypedDict aliasing.
+ #
+ # For Pydantic models, whether we should pre-dealias depends on how the model encodes aliasing:
+ # - If the model uses real Pydantic aliases (pydantic.Field(alias=...)), then we must pass wire keys through
+ # unchanged so Pydantic can validate them.
+ # - If the model encodes aliasing only via FieldMetadata annotations, then we MUST pre-dealias because Pydantic
+ # will not recognize those aliases during validation.
+ if inspect.isclass(type_) and issubclass(type_, pydantic.BaseModel):
+ has_pydantic_aliases = bool(_get_field_aliases(type_)[0])
+
+ dealiased_object = (
+ object_
+ if has_pydantic_aliases
+ else convert_and_respect_annotation_metadata(object_=object_, annotation=type_, direction="read")
+ )
+ else:
+ dealiased_object = convert_and_respect_annotation_metadata(object_=object_, annotation=type_, direction="read")
if IS_PYDANTIC_V2:
- adapter = pydantic.TypeAdapter(type_) # type: ignore[attr-defined]
- return adapter.validate_python(dealiased_object)
+ adapter = _get_type_adapter(type_)
+ return adapter.validate_python(dealiased_object) # type: ignore[no-any-return]
return pydantic.parse_obj_as(type_, dealiased_object)
@@ -59,9 +276,14 @@ class UniversalBaseModel(pydantic.BaseModel):
protected_namespaces=(),
)
+ @pydantic.model_validator(mode="before") # type: ignore[attr-defined]
+ @classmethod
+ def _coerce_field_names_to_aliases(cls, data: Any) -> Any:
+ return _coerce_keys_to_aliases(cls, data)
+
@pydantic.model_serializer(mode="plain", when_used="json") # type: ignore[attr-defined]
def serialize_model(self) -> Any: # type: ignore[name-defined]
- serialized = self.model_dump()
+ serialized = self.dict() # type: ignore[attr-defined]
data = {k: serialize_datetime(v) if isinstance(v, dt.datetime) else v for k, v in serialized.items()}
return data
@@ -71,6 +293,10 @@ class Config:
smart_union = True
json_encoders = {dt.datetime: serialize_datetime}
+ @pydantic.root_validator(pre=True)
+ def _coerce_field_names_to_aliases(cls, values: Any) -> Any:
+ return _coerce_keys_to_aliases(cls, values) # type: ignore[arg-type]
+
@classmethod
def model_construct(cls: Type["Model"], _fields_set: Optional[Set[str]] = None, **values: Any) -> "Model":
dealiased_object = convert_and_respect_annotation_metadata(object_=values, annotation=cls, direction="read")
@@ -147,7 +373,10 @@ def dict(self, **kwargs: Any) -> Dict[str, Any]:
dict_dump = super().dict(**kwargs_with_defaults_exclude_unset_include_fields)
- return convert_and_respect_annotation_metadata(object_=dict_dump, annotation=self.__class__, direction="write")
+ return cast(
+ Dict[str, Any],
+ convert_and_respect_annotation_metadata(object_=dict_dump, annotation=self.__class__, direction="write"),
+ )
def _union_list_of_pydantic_dicts(source: List[Any], destination: List[Any]) -> List[Any]:
@@ -217,7 +446,9 @@ def universal_root_validator(
) -> Callable[[AnyCallable], AnyCallable]:
def decorator(func: AnyCallable) -> AnyCallable:
if IS_PYDANTIC_V2:
- return cast(AnyCallable, pydantic.model_validator(mode="before" if pre else "after")(func)) # type: ignore[attr-defined]
+ # In Pydantic v2, for RootModel we always use "before" mode
+ # The custom validators transform the input value before the model is created
+ return cast(AnyCallable, pydantic.model_validator(mode="before")(func)) # type: ignore[attr-defined]
return cast(AnyCallable, pydantic.root_validator(pre=pre)(func)) # type: ignore[call-overload]
return decorator
@@ -232,7 +463,7 @@ def decorator(func: AnyCallable) -> AnyCallable:
return decorator
-PydanticField = Union[ModelField, pydantic.fields.FieldInfo]
+PydanticField = Union[ModelField, _FieldInfo]
def _get_model_fields(model: Type["Model"]) -> Mapping[str, PydanticField]:
diff --git a/skyvault/skyflow/generated/rest/core/request_options.py b/skyvault/skyflow/generated/rest/core/request_options.py
index 1b388044..caa6f669 100644
--- a/skyvault/skyflow/generated/rest/core/request_options.py
+++ b/skyvault/skyflow/generated/rest/core/request_options.py
@@ -14,7 +14,9 @@ class RequestOptions(typing.TypedDict, total=False):
This is used primarily as an optional final parameter for service functions.
Attributes:
- - timeout_in_seconds: int. The number of seconds to await an API call before timing out.
+ - timeout: float. The number of seconds to await an API call before timing out.
+
+ - timeout_in_seconds: int. Deprecated alias for `timeout`; both are in seconds. Prefer `timeout`.
- max_retries: int. The max number of retries to attempt if the API call fails.
@@ -27,9 +29,12 @@ class RequestOptions(typing.TypedDict, total=False):
- chunk_size: int. The size, in bytes, to process each chunk of data being streamed back within the response. This equates to leveraging `chunk_size` within `requests` or `httpx`, and is only leveraged for file downloads.
"""
+ timeout: NotRequired[float]
timeout_in_seconds: NotRequired[int]
max_retries: NotRequired[int]
additional_headers: NotRequired[typing.Dict[str, typing.Any]]
additional_query_parameters: NotRequired[typing.Dict[str, typing.Any]]
additional_body_parameters: NotRequired[typing.Dict[str, typing.Any]]
chunk_size: NotRequired[int]
+ stream_reconnection_enabled: NotRequired[bool]
+ max_stream_reconnection_attempts: NotRequired[int]
diff --git a/skyvault/skyflow/generated/rest/core/serialization.py b/skyvault/skyflow/generated/rest/core/serialization.py
index c36e865c..1d753e26 100644
--- a/skyvault/skyflow/generated/rest/core/serialization.py
+++ b/skyvault/skyflow/generated/rest/core/serialization.py
@@ -26,6 +26,75 @@ def __init__(self, *, alias: str) -> None:
self.alias = alias
+# Resolving type hints (typing.get_type_hints) is expensive because it eval/compiles
+# forward-reference annotations. The result is constant for a given type, so we cache it.
+# This is critical for hot paths like SSE event parsing, where the same (often large
+# discriminated-union) type is converted on every single event.
+_type_hints_cache: typing.Dict[typing.Any, typing.Dict[str, typing.Any]] = {}
+
+
+def _get_cached_type_hints(expected_type: typing.Any) -> typing.Dict[str, typing.Any]:
+ try:
+ cached = _type_hints_cache.get(expected_type)
+ except TypeError:
+ # Unhashable type; resolve without caching.
+ return _resolve_type_hints(expected_type)
+ if cached is None:
+ cached = _resolve_type_hints(expected_type)
+ _type_hints_cache[expected_type] = cached
+ return cached
+
+
+def _resolve_type_hints(expected_type: typing.Any) -> typing.Dict[str, typing.Any]:
+ try:
+ return typing_extensions.get_type_hints(expected_type, include_extras=True)
+ except NameError:
+ # The type contains a circular reference, so we use the __annotations__ attribute directly.
+ return getattr(expected_type, "__annotations__", {})
+
+
+# Whether convert_and_respect_annotation_metadata can possibly rewrite anything for a given
+# annotation, i.e. whether any reachable model/TypedDict field carries a FieldMetadata alias.
+# This is constant per type, so we cache it and use it to short-circuit the recursive walk.
+_requires_conversion_cache: typing.Dict[typing.Any, bool] = {}
+
+
+def _requires_conversion(type_: typing.Any) -> bool:
+ try:
+ cached = _requires_conversion_cache.get(type_)
+ except TypeError:
+ # Unhashable annotation; compute without caching.
+ return _compute_requires_conversion(type_, set())
+ if cached is None:
+ cached = _compute_requires_conversion(type_, set())
+ _requires_conversion_cache[type_] = cached
+ return cached
+
+
+def _compute_requires_conversion(type_: typing.Any, seen: typing.Set[typing.Any]) -> bool:
+ clean_type = _remove_annotations(type_)
+
+ try:
+ if clean_type in seen:
+ return False
+ seen = seen | {clean_type}
+ except TypeError:
+ # Unhashable type; skip cycle tracking (the type graph is finite in practice).
+ pass
+
+ # Models / TypedDicts: a field alias here means we must dealias; otherwise recurse into fields.
+ if (inspect.isclass(clean_type) and issubclass(clean_type, pydantic.BaseModel)) or typing_extensions.is_typeddict(
+ clean_type
+ ):
+ annotations = _get_cached_type_hints(clean_type)
+ if _get_alias_to_field_name(annotations):
+ return True
+ return any(_compute_requires_conversion(hint, seen) for hint in annotations.values())
+
+ # Containers / unions: recurse into the type arguments (List/Set/Sequence/Dict/Union/etc.).
+ return any(_compute_requires_conversion(arg, seen) for arg in typing_extensions.get_args(clean_type))
+
+
def convert_and_respect_annotation_metadata(
*,
object_: typing.Any,
@@ -57,6 +126,13 @@ def convert_and_respect_annotation_metadata(
return None
if inner_type is None:
inner_type = annotation
+ # The only thing this function ever rewrites is keys that carry a FieldMetadata
+ # alias. If nothing in the (cached) type graph has such an alias, the conversion is
+ # a content-identity transform, so we can skip the entire recursive walk. This is
+ # the hot path for SSE streaming, where a large discriminated union would otherwise
+ # be traversed on every single event.
+ if not _requires_conversion(annotation):
+ return object_
clean_type = _remove_annotations(inner_type)
# Pydantic models
@@ -160,12 +236,7 @@ def _convert_mapping(
direction: typing.Literal["read", "write"],
) -> typing.Mapping[str, object]:
converted_object: typing.Dict[str, object] = {}
- try:
- annotations = typing_extensions.get_type_hints(expected_type, include_extras=True)
- except NameError:
- # The TypedDict contains a circular reference, so
- # we use the __annotations__ attribute directly.
- annotations = getattr(expected_type, "__annotations__", {})
+ annotations = _get_cached_type_hints(expected_type)
aliases_to_field_names = _get_alias_to_field_name(annotations)
for key, value in object_.items():
if direction == "read" and key in aliases_to_field_names:
@@ -221,12 +292,12 @@ def _remove_annotations(type_: typing.Any) -> typing.Any:
def get_alias_to_field_mapping(type_: typing.Any) -> typing.Dict[str, str]:
- annotations = typing_extensions.get_type_hints(type_, include_extras=True)
+ annotations = _get_cached_type_hints(type_)
return _get_alias_to_field_name(annotations)
def get_field_to_alias_mapping(type_: typing.Any) -> typing.Dict[str, str]:
- annotations = typing_extensions.get_type_hints(type_, include_extras=True)
+ annotations = _get_cached_type_hints(type_)
return _get_field_to_alias_name(annotations)
diff --git a/skyvault/skyflow/generated/rest/environment.py b/skyvault/skyflow/generated/rest/environment.py
index 8c4747ca..3aa335bb 100644
--- a/skyvault/skyflow/generated/rest/environment.py
+++ b/skyvault/skyflow/generated/rest/environment.py
@@ -3,6 +3,6 @@
import enum
-class SkyflowEnvironment(enum.Enum):
- PRODUCTION = "https://identifier.vault.skyflowapis.com"
- SANDBOX = "https://identifier.vault.skyflowapis-preview.com"
+class SkyflowAuthEnvironment(enum.Enum):
+ PRODUCTION = "https://%7B%7Bvault_uri%7D%7D.vault.skyflowapis.com"
+ SANDBOX = "https://%7B%7Bvault_uri%7D%7D.vault.skyflowapis-preview.com"
diff --git a/skyvault/skyflow/generated/rest/errors/__init__.py b/skyvault/skyflow/generated/rest/errors/__init__.py
index 27c36553..8810eed8 100644
--- a/skyvault/skyflow/generated/rest/errors/__init__.py
+++ b/skyvault/skyflow/generated/rest/errors/__init__.py
@@ -2,9 +2,41 @@
# isort: skip_file
-from .bad_request_error import BadRequestError
-from .internal_server_error import InternalServerError
-from .not_found_error import NotFoundError
-from .unauthorized_error import UnauthorizedError
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .bad_request_error import BadRequestError
+ from .internal_server_error import InternalServerError
+ from .not_found_error import NotFoundError
+ from .unauthorized_error import UnauthorizedError
+_dynamic_imports: typing.Dict[str, str] = {
+ "BadRequestError": ".bad_request_error",
+ "InternalServerError": ".internal_server_error",
+ "NotFoundError": ".not_found_error",
+ "UnauthorizedError": ".unauthorized_error",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
__all__ = ["BadRequestError", "InternalServerError", "NotFoundError", "UnauthorizedError"]
diff --git a/skyvault/skyflow/generated/rest/errors/bad_request_error.py b/skyvault/skyflow/generated/rest/errors/bad_request_error.py
index baf5be4f..92449913 100644
--- a/skyvault/skyflow/generated/rest/errors/bad_request_error.py
+++ b/skyvault/skyflow/generated/rest/errors/bad_request_error.py
@@ -3,8 +3,9 @@
import typing
from ..core.api_error import ApiError
+from ..types.error_response import ErrorResponse
class BadRequestError(ApiError):
- def __init__(self, body: typing.Optional[typing.Any], headers: typing.Optional[typing.Dict[str, str]] = None):
+ def __init__(self, body: ErrorResponse, headers: typing.Optional[typing.Dict[str, str]] = None):
super().__init__(status_code=400, headers=headers, body=body)
diff --git a/skyvault/skyflow/generated/rest/errors/not_found_error.py b/skyvault/skyflow/generated/rest/errors/not_found_error.py
index dcd60e38..3b2a2d1f 100644
--- a/skyvault/skyflow/generated/rest/errors/not_found_error.py
+++ b/skyvault/skyflow/generated/rest/errors/not_found_error.py
@@ -3,8 +3,9 @@
import typing
from ..core.api_error import ApiError
+from ..types.error_response import ErrorResponse
class NotFoundError(ApiError):
- def __init__(self, body: typing.Optional[typing.Any], headers: typing.Optional[typing.Dict[str, str]] = None):
+ def __init__(self, body: ErrorResponse, headers: typing.Optional[typing.Dict[str, str]] = None):
super().__init__(status_code=404, headers=headers, body=body)
diff --git a/skyvault/skyflow/generated/rest/errors/unauthorized_error.py b/skyvault/skyflow/generated/rest/errors/unauthorized_error.py
index c83b25c2..00a614a3 100644
--- a/skyvault/skyflow/generated/rest/errors/unauthorized_error.py
+++ b/skyvault/skyflow/generated/rest/errors/unauthorized_error.py
@@ -3,8 +3,9 @@
import typing
from ..core.api_error import ApiError
+from ..types.error_response import ErrorResponse
class UnauthorizedError(ApiError):
- def __init__(self, body: typing.Optional[typing.Any], headers: typing.Optional[typing.Dict[str, str]] = None):
+ def __init__(self, body: ErrorResponse, headers: typing.Optional[typing.Dict[str, str]] = None):
super().__init__(status_code=401, headers=headers, body=body)
diff --git a/skyvault/skyflow/generated/rest/files/__init__.py b/skyvault/skyflow/generated/rest/files/__init__.py
index f313ad67..5cde0202 100644
--- a/skyvault/skyflow/generated/rest/files/__init__.py
+++ b/skyvault/skyflow/generated/rest/files/__init__.py
@@ -2,30 +2,3 @@
# isort: skip_file
-from .types import (
- DeidentifyFileAudioRequestDeidentifyAudioEntityTypesItem,
- DeidentifyFileAudioRequestDeidentifyAudioOutputTranscription,
- DeidentifyFileDocumentPdfRequestDeidentifyPdfEntityTypesItem,
- DeidentifyFileImageRequestDeidentifyImageEntityTypesItem,
- DeidentifyFileImageRequestDeidentifyImageMaskingMethod,
- DeidentifyFileRequestDeidentifyDocumentEntityTypesItem,
- DeidentifyFileRequestDeidentifyPresentationEntityTypesItem,
- DeidentifyFileRequestDeidentifySpreadsheetEntityTypesItem,
- DeidentifyFileRequestDeidentifyStructuredTextEntityTypesItem,
- DeidentifyFileRequestDeidentifyTextEntityTypesItem,
- DeidentifyFileRequestEntityTypesItem,
-)
-
-__all__ = [
- "DeidentifyFileAudioRequestDeidentifyAudioEntityTypesItem",
- "DeidentifyFileAudioRequestDeidentifyAudioOutputTranscription",
- "DeidentifyFileDocumentPdfRequestDeidentifyPdfEntityTypesItem",
- "DeidentifyFileImageRequestDeidentifyImageEntityTypesItem",
- "DeidentifyFileImageRequestDeidentifyImageMaskingMethod",
- "DeidentifyFileRequestDeidentifyDocumentEntityTypesItem",
- "DeidentifyFileRequestDeidentifyPresentationEntityTypesItem",
- "DeidentifyFileRequestDeidentifySpreadsheetEntityTypesItem",
- "DeidentifyFileRequestDeidentifyStructuredTextEntityTypesItem",
- "DeidentifyFileRequestDeidentifyTextEntityTypesItem",
- "DeidentifyFileRequestEntityTypesItem",
-]
diff --git a/skyvault/skyflow/generated/rest/files/client.py b/skyvault/skyflow/generated/rest/files/client.py
index 539d2161..dc8bf433 100644
--- a/skyvault/skyflow/generated/rest/files/client.py
+++ b/skyvault/skyflow/generated/rest/files/client.py
@@ -2,56 +2,11 @@
import typing
+from .. import core
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.request_options import RequestOptions
-from ..types.deidentify_file_response import DeidentifyFileResponse
-from ..types.detect_runs_response import DetectRunsResponse
-from ..types.file_data import FileData
-from ..types.file_data_deidentify_audio import FileDataDeidentifyAudio
-from ..types.file_data_deidentify_document import FileDataDeidentifyDocument
-from ..types.file_data_deidentify_image import FileDataDeidentifyImage
-from ..types.file_data_deidentify_pdf import FileDataDeidentifyPdf
-from ..types.file_data_deidentify_presentation import FileDataDeidentifyPresentation
-from ..types.file_data_deidentify_spreadsheet import FileDataDeidentifySpreadsheet
-from ..types.file_data_deidentify_structured_text import FileDataDeidentifyStructuredText
-from ..types.file_data_deidentify_text import FileDataDeidentifyText
-from ..types.file_data_reidentify_file import FileDataReidentifyFile
-from ..types.format import Format
-from ..types.reidentify_file_response import ReidentifyFileResponse
-from ..types.token_type_mapping import TokenTypeMapping
-from ..types.transformations import Transformations
+from ..types.upload_file_response_v2 import UploadFileResponseV2
from .raw_client import AsyncRawFilesClient, RawFilesClient
-from .types.deidentify_file_audio_request_deidentify_audio_entity_types_item import (
- DeidentifyFileAudioRequestDeidentifyAudioEntityTypesItem,
-)
-from .types.deidentify_file_audio_request_deidentify_audio_output_transcription import (
- DeidentifyFileAudioRequestDeidentifyAudioOutputTranscription,
-)
-from .types.deidentify_file_document_pdf_request_deidentify_pdf_entity_types_item import (
- DeidentifyFileDocumentPdfRequestDeidentifyPdfEntityTypesItem,
-)
-from .types.deidentify_file_image_request_deidentify_image_entity_types_item import (
- DeidentifyFileImageRequestDeidentifyImageEntityTypesItem,
-)
-from .types.deidentify_file_image_request_deidentify_image_masking_method import (
- DeidentifyFileImageRequestDeidentifyImageMaskingMethod,
-)
-from .types.deidentify_file_request_deidentify_document_entity_types_item import (
- DeidentifyFileRequestDeidentifyDocumentEntityTypesItem,
-)
-from .types.deidentify_file_request_deidentify_presentation_entity_types_item import (
- DeidentifyFileRequestDeidentifyPresentationEntityTypesItem,
-)
-from .types.deidentify_file_request_deidentify_spreadsheet_entity_types_item import (
- DeidentifyFileRequestDeidentifySpreadsheetEntityTypesItem,
-)
-from .types.deidentify_file_request_deidentify_structured_text_entity_types_item import (
- DeidentifyFileRequestDeidentifyStructuredTextEntityTypesItem,
-)
-from .types.deidentify_file_request_deidentify_text_entity_types_item import (
- DeidentifyFileRequestDeidentifyTextEntityTypesItem,
-)
-from .types.deidentify_file_request_entity_types_item import DeidentifyFileRequestEntityTypesItem
# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)
@@ -72,1752 +27,156 @@ def with_raw_response(self) -> RawFilesClient:
"""
return self._raw_client
- def deidentify_file(
+ def upload_file_v2(
self,
- *,
- file: FileData,
- vault_id: str,
- entity_types: typing.Optional[typing.Sequence[DeidentifyFileRequestEntityTypesItem]] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> DeidentifyFileResponse:
- """
- De-identifies sensitive data from a file. This operation includes options applicable to all supported file types.
For more specific options, see the category-specific operations (like De-identify Document) and the file type-specific opertions (like De-identify PDF).
-
- Parameters
- ----------
- file : FileData
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileRequestEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- DeidentifyFileResponse
- OK
-
- Examples
- --------
- from skyflow import FileData, Skyflow
-
- client = Skyflow(
- token="YOUR_TOKEN",
- )
- client.files.deidentify_file(
- file=FileData(
- base_64="base64",
- data_format="mp3",
- ),
- vault_id="vault_id",
- )
- """
- _response = self._raw_client.deidentify_file(
- file=file,
- vault_id=vault_id,
- entity_types=entity_types,
- token_type=token_type,
- allow_regex=allow_regex,
- restrict_regex=restrict_regex,
- transformations=transformations,
- configuration_id=configuration_id,
- request_options=request_options,
- )
- return _response.data
-
- def deidentify_audio(
- self,
- *,
- file: FileDataDeidentifyAudio,
- vault_id: str,
- output_transcription: typing.Optional[DeidentifyFileAudioRequestDeidentifyAudioOutputTranscription] = OMIT,
- output_processed_audio: typing.Optional[bool] = OMIT,
- bleep_start_padding: typing.Optional[float] = OMIT,
- bleep_stop_padding: typing.Optional[float] = OMIT,
- bleep_frequency: typing.Optional[int] = OMIT,
- bleep_gain: typing.Optional[int] = OMIT,
- entity_types: typing.Optional[typing.Sequence[DeidentifyFileAudioRequestDeidentifyAudioEntityTypesItem]] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> DeidentifyFileResponse:
- """
- De-identifies sensitive data from an audio file. This operation includes options applicable to all supported audio file types.
For broader file type support, see De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifyAudio
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- output_transcription : typing.Optional[DeidentifyFileAudioRequestDeidentifyAudioOutputTranscription]
- Type of transcription to output.
-
- output_processed_audio : typing.Optional[bool]
- Whether to include the processed audio file in the response.
-
- bleep_start_padding : typing.Optional[float]
- Padding added to the beginning of a bleep, in seconds.
-
- bleep_stop_padding : typing.Optional[float]
- Padding added to the end of a bleep, in seconds.
-
- bleep_frequency : typing.Optional[int]
- The pitch of the bleep sound, in Hz. The higher the number, the higher the pitch.
-
- bleep_gain : typing.Optional[int]
- Relative loudness of the bleep in dB. Positive values increase its loudness, and negative values decrease it.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileAudioRequestDeidentifyAudioEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- DeidentifyFileResponse
- OK
-
- Examples
- --------
- from skyflow import FileDataDeidentifyAudio, Skyflow
-
- client = Skyflow(
- token="YOUR_TOKEN",
- )
- client.files.deidentify_audio(
- file=FileDataDeidentifyAudio(
- base_64="base64",
- data_format="mp3",
- ),
- vault_id="vault_id",
- )
- """
- _response = self._raw_client.deidentify_audio(
- file=file,
- vault_id=vault_id,
- output_transcription=output_transcription,
- output_processed_audio=output_processed_audio,
- bleep_start_padding=bleep_start_padding,
- bleep_stop_padding=bleep_stop_padding,
- bleep_frequency=bleep_frequency,
- bleep_gain=bleep_gain,
- entity_types=entity_types,
- token_type=token_type,
- allow_regex=allow_regex,
- restrict_regex=restrict_regex,
- transformations=transformations,
- configuration_id=configuration_id,
- request_options=request_options,
- )
- return _response.data
-
- def deidentify_document(
- self,
- *,
- file: FileDataDeidentifyDocument,
- vault_id: str,
- entity_types: typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifyDocumentEntityTypesItem]] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> DeidentifyFileResponse:
- """
- De-identifies sensitive data from a document file. This operation includes options applicable to all supported document file types.
For more specific options, see the file type-specific opertions (like De-identify PDF) where they're available. For broader file type support, see De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifyDocument
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifyDocumentEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- DeidentifyFileResponse
- OK
-
- Examples
- --------
- from skyflow import FileDataDeidentifyDocument, Skyflow
-
- client = Skyflow(
- token="YOUR_TOKEN",
- )
- client.files.deidentify_document(
- file=FileDataDeidentifyDocument(
- base_64="base64",
- data_format="pdf",
- ),
- vault_id="vault_id",
- )
- """
- _response = self._raw_client.deidentify_document(
- file=file,
- vault_id=vault_id,
- entity_types=entity_types,
- token_type=token_type,
- allow_regex=allow_regex,
- restrict_regex=restrict_regex,
- transformations=transformations,
- configuration_id=configuration_id,
- request_options=request_options,
- )
- return _response.data
-
- def deidentify_pdf(
- self,
- *,
- file: FileDataDeidentifyPdf,
- vault_id: str,
- density: typing.Optional[int] = OMIT,
- max_resolution: typing.Optional[int] = OMIT,
- entity_types: typing.Optional[
- typing.Sequence[DeidentifyFileDocumentPdfRequestDeidentifyPdfEntityTypesItem]
- ] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> DeidentifyFileResponse:
- """
- De-identifies sensitive data from a PDF file. This operation includes options specific to PDF files.
For broader file type support, see De-identify Document and De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifyPdf
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- density : typing.Optional[int]
- Pixel density at which to process the PDF file.
-
- max_resolution : typing.Optional[int]
- Max resolution at which to process the PDF file.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileDocumentPdfRequestDeidentifyPdfEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- DeidentifyFileResponse
- OK
-
- Examples
- --------
- from skyflow import FileDataDeidentifyPdf, Skyflow
-
- client = Skyflow(
- token="YOUR_TOKEN",
- )
- client.files.deidentify_pdf(
- file=FileDataDeidentifyPdf(
- base_64="base64",
- ),
- vault_id="vault_id",
- )
- """
- _response = self._raw_client.deidentify_pdf(
- file=file,
- vault_id=vault_id,
- density=density,
- max_resolution=max_resolution,
- entity_types=entity_types,
- token_type=token_type,
- allow_regex=allow_regex,
- restrict_regex=restrict_regex,
- transformations=transformations,
- configuration_id=configuration_id,
- request_options=request_options,
- )
- return _response.data
-
- def deidentify_image(
- self,
- *,
- file: FileDataDeidentifyImage,
- vault_id: str,
- output_processed_image: typing.Optional[bool] = OMIT,
- output_ocr_text: typing.Optional[bool] = OMIT,
- masking_method: typing.Optional[DeidentifyFileImageRequestDeidentifyImageMaskingMethod] = OMIT,
- entity_types: typing.Optional[typing.Sequence[DeidentifyFileImageRequestDeidentifyImageEntityTypesItem]] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> DeidentifyFileResponse:
- """
- De-identifies sensitive data from an image file. This operation includes options applicable to all supported image file types.
For broader file type support, see De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifyImage
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- output_processed_image : typing.Optional[bool]
- If `true`, includes processed image in the output.
-
- output_ocr_text : typing.Optional[bool]
- If `true`, includes text detected by OCR in the response.
-
- masking_method : typing.Optional[DeidentifyFileImageRequestDeidentifyImageMaskingMethod]
- Method to mask the entities in the image.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileImageRequestDeidentifyImageEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- DeidentifyFileResponse
- OK
-
- Examples
- --------
- from skyflow import FileDataDeidentifyImage, Skyflow
-
- client = Skyflow(
- token="YOUR_TOKEN",
- )
- client.files.deidentify_image(
- file=FileDataDeidentifyImage(
- base_64="base64",
- data_format="jpg",
- ),
- vault_id="vault_id",
- )
- """
- _response = self._raw_client.deidentify_image(
- file=file,
- vault_id=vault_id,
- output_processed_image=output_processed_image,
- output_ocr_text=output_ocr_text,
- masking_method=masking_method,
- entity_types=entity_types,
- token_type=token_type,
- allow_regex=allow_regex,
- restrict_regex=restrict_regex,
- transformations=transformations,
- configuration_id=configuration_id,
- request_options=request_options,
- )
- return _response.data
-
- def deidentify_presentation(
- self,
- *,
- file: FileDataDeidentifyPresentation,
- vault_id: str,
- entity_types: typing.Optional[
- typing.Sequence[DeidentifyFileRequestDeidentifyPresentationEntityTypesItem]
- ] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> DeidentifyFileResponse:
- """
- De-identifies sensitive data from a presentation file. This operation includes options applicable to all supported presentation file types.
For broader file type support, see De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifyPresentation
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifyPresentationEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- DeidentifyFileResponse
- OK
-
- Examples
- --------
- from skyflow import FileDataDeidentifyPresentation, Skyflow
-
- client = Skyflow(
- token="YOUR_TOKEN",
- )
- client.files.deidentify_presentation(
- file=FileDataDeidentifyPresentation(
- base_64="base64",
- data_format="ppt",
- ),
- vault_id="vault_id",
- )
- """
- _response = self._raw_client.deidentify_presentation(
- file=file,
- vault_id=vault_id,
- entity_types=entity_types,
- token_type=token_type,
- allow_regex=allow_regex,
- restrict_regex=restrict_regex,
- transformations=transformations,
- configuration_id=configuration_id,
- request_options=request_options,
- )
- return _response.data
-
- def deidentify_spreadsheet(
- self,
- *,
- file: FileDataDeidentifySpreadsheet,
- vault_id: str,
- entity_types: typing.Optional[
- typing.Sequence[DeidentifyFileRequestDeidentifySpreadsheetEntityTypesItem]
- ] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> DeidentifyFileResponse:
- """
- De-identifies sensitive data from a spreadsheet file. This operation includes options applicable to all supported spreadsheet file types.
For broader file type support, see De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifySpreadsheet
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifySpreadsheetEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- DeidentifyFileResponse
- OK
-
- Examples
- --------
- from skyflow import FileDataDeidentifySpreadsheet, Skyflow
-
- client = Skyflow(
- token="YOUR_TOKEN",
- )
- client.files.deidentify_spreadsheet(
- file=FileDataDeidentifySpreadsheet(
- base_64="base64",
- data_format="csv",
- ),
- vault_id="vault_id",
- )
- """
- _response = self._raw_client.deidentify_spreadsheet(
- file=file,
- vault_id=vault_id,
- entity_types=entity_types,
- token_type=token_type,
- allow_regex=allow_regex,
- restrict_regex=restrict_regex,
- transformations=transformations,
- configuration_id=configuration_id,
- request_options=request_options,
- )
- return _response.data
-
- def deidentify_structured_text(
- self,
- *,
- file: FileDataDeidentifyStructuredText,
- vault_id: str,
- entity_types: typing.Optional[
- typing.Sequence[DeidentifyFileRequestDeidentifyStructuredTextEntityTypesItem]
- ] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> DeidentifyFileResponse:
- """
- De-identifies sensitive data from a structured text file. This operation includes options applicable to all supported structured text file types.
For broader file type support, see De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifyStructuredText
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifyStructuredTextEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- DeidentifyFileResponse
- OK
-
- Examples
- --------
- from skyflow import FileDataDeidentifyStructuredText, Skyflow
-
- client = Skyflow(
- token="YOUR_TOKEN",
- )
- client.files.deidentify_structured_text(
- file=FileDataDeidentifyStructuredText(
- base_64="base64",
- data_format="json",
- ),
- vault_id="vault_id",
- )
- """
- _response = self._raw_client.deidentify_structured_text(
- file=file,
- vault_id=vault_id,
- entity_types=entity_types,
- token_type=token_type,
- allow_regex=allow_regex,
- restrict_regex=restrict_regex,
- transformations=transformations,
- configuration_id=configuration_id,
- request_options=request_options,
- )
- return _response.data
-
- def deidentify_text(
- self,
- *,
- file: FileDataDeidentifyText,
- vault_id: str,
- entity_types: typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifyTextEntityTypesItem]] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> DeidentifyFileResponse:
- """
- De-identifies sensitive data from a text file. This operation includes options applicable to all supported image text types.
For broader file type support, see De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifyText
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifyTextEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- DeidentifyFileResponse
- OK
-
- Examples
- --------
- from skyflow import FileDataDeidentifyText, Skyflow
-
- client = Skyflow(
- token="YOUR_TOKEN",
- )
- client.files.deidentify_text(
- file=FileDataDeidentifyText(
- base_64="base64",
- ),
- vault_id="vault_id",
- )
- """
- _response = self._raw_client.deidentify_text(
- file=file,
- vault_id=vault_id,
- entity_types=entity_types,
- token_type=token_type,
- allow_regex=allow_regex,
- restrict_regex=restrict_regex,
- transformations=transformations,
- configuration_id=configuration_id,
- request_options=request_options,
- )
- return _response.data
-
- def reidentify_file(
- self,
- *,
- file: FileDataReidentifyFile,
- vault_id: str,
- format: typing.Optional[Format] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> ReidentifyFileResponse:
- """
- Re-identifies tokens in a file.
-
- Parameters
- ----------
- file : FileDataReidentifyFile
-
- vault_id : str
- ID of the vault where the entities are stored.
-
- format : typing.Optional[Format]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ReidentifyFileResponse
- OK
-
- Examples
- --------
- from skyflow import FileDataReidentifyFile, Skyflow
-
- client = Skyflow(
- token="YOUR_TOKEN",
- )
- client.files.reidentify_file(
- file=FileDataReidentifyFile(
- base_64="base64",
- data_format="txt",
- ),
- vault_id="vault_id",
- )
- """
- _response = self._raw_client.reidentify_file(
- file=file, vault_id=vault_id, format=format, request_options=request_options
- )
- return _response.data
-
- def get_run(
- self,
- run_id: str,
- *,
- vault_id: typing.Optional[str] = None,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> DetectRunsResponse:
- """
- Returns the status of a detect run.
-
- Parameters
- ----------
- run_id : str
-
- vault_id : typing.Optional[str]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- DetectRunsResponse
- OK
-
- Examples
- --------
- from skyflow import Skyflow
-
- client = Skyflow(
- token="YOUR_TOKEN",
- )
- client.files.get_run(
- run_id="run_id",
- vault_id="vault_id",
- )
- """
- _response = self._raw_client.get_run(run_id, vault_id=vault_id, request_options=request_options)
- return _response.data
-
-
-class AsyncFilesClient:
- def __init__(self, *, client_wrapper: AsyncClientWrapper):
- self._raw_client = AsyncRawFilesClient(client_wrapper=client_wrapper)
-
- @property
- def with_raw_response(self) -> AsyncRawFilesClient:
- """
- Retrieves a raw implementation of this client that returns raw responses.
-
- Returns
- -------
- AsyncRawFilesClient
- """
- return self._raw_client
-
- async def deidentify_file(
- self,
- *,
- file: FileData,
- vault_id: str,
- entity_types: typing.Optional[typing.Sequence[DeidentifyFileRequestEntityTypesItem]] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> DeidentifyFileResponse:
- """
- De-identifies sensitive data from a file. This operation includes options applicable to all supported file types.
For more specific options, see the category-specific operations (like De-identify Document) and the file type-specific opertions (like De-identify PDF).
-
- Parameters
- ----------
- file : FileData
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileRequestEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- DeidentifyFileResponse
- OK
-
- Examples
- --------
- import asyncio
-
- from skyflow import AsyncSkyflow, FileData
-
- client = AsyncSkyflow(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.files.deidentify_file(
- file=FileData(
- base_64="base64",
- data_format="mp3",
- ),
- vault_id="vault_id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._raw_client.deidentify_file(
- file=file,
- vault_id=vault_id,
- entity_types=entity_types,
- token_type=token_type,
- allow_regex=allow_regex,
- restrict_regex=restrict_regex,
- transformations=transformations,
- configuration_id=configuration_id,
- request_options=request_options,
- )
- return _response.data
-
- async def deidentify_audio(
- self,
- *,
- file: FileDataDeidentifyAudio,
- vault_id: str,
- output_transcription: typing.Optional[DeidentifyFileAudioRequestDeidentifyAudioOutputTranscription] = OMIT,
- output_processed_audio: typing.Optional[bool] = OMIT,
- bleep_start_padding: typing.Optional[float] = OMIT,
- bleep_stop_padding: typing.Optional[float] = OMIT,
- bleep_frequency: typing.Optional[int] = OMIT,
- bleep_gain: typing.Optional[int] = OMIT,
- entity_types: typing.Optional[typing.Sequence[DeidentifyFileAudioRequestDeidentifyAudioEntityTypesItem]] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> DeidentifyFileResponse:
- """
- De-identifies sensitive data from an audio file. This operation includes options applicable to all supported audio file types.
For broader file type support, see De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifyAudio
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- output_transcription : typing.Optional[DeidentifyFileAudioRequestDeidentifyAudioOutputTranscription]
- Type of transcription to output.
-
- output_processed_audio : typing.Optional[bool]
- Whether to include the processed audio file in the response.
-
- bleep_start_padding : typing.Optional[float]
- Padding added to the beginning of a bleep, in seconds.
-
- bleep_stop_padding : typing.Optional[float]
- Padding added to the end of a bleep, in seconds.
-
- bleep_frequency : typing.Optional[int]
- The pitch of the bleep sound, in Hz. The higher the number, the higher the pitch.
-
- bleep_gain : typing.Optional[int]
- Relative loudness of the bleep in dB. Positive values increase its loudness, and negative values decrease it.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileAudioRequestDeidentifyAudioEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- DeidentifyFileResponse
- OK
-
- Examples
- --------
- import asyncio
-
- from skyflow import AsyncSkyflow, FileDataDeidentifyAudio
-
- client = AsyncSkyflow(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.files.deidentify_audio(
- file=FileDataDeidentifyAudio(
- base_64="base64",
- data_format="mp3",
- ),
- vault_id="vault_id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._raw_client.deidentify_audio(
- file=file,
- vault_id=vault_id,
- output_transcription=output_transcription,
- output_processed_audio=output_processed_audio,
- bleep_start_padding=bleep_start_padding,
- bleep_stop_padding=bleep_stop_padding,
- bleep_frequency=bleep_frequency,
- bleep_gain=bleep_gain,
- entity_types=entity_types,
- token_type=token_type,
- allow_regex=allow_regex,
- restrict_regex=restrict_regex,
- transformations=transformations,
- configuration_id=configuration_id,
- request_options=request_options,
- )
- return _response.data
-
- async def deidentify_document(
- self,
- *,
- file: FileDataDeidentifyDocument,
- vault_id: str,
- entity_types: typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifyDocumentEntityTypesItem]] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> DeidentifyFileResponse:
- """
- De-identifies sensitive data from a document file. This operation includes options applicable to all supported document file types.
For more specific options, see the file type-specific opertions (like De-identify PDF) where they're available. For broader file type support, see De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifyDocument
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifyDocumentEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- DeidentifyFileResponse
- OK
-
- Examples
- --------
- import asyncio
-
- from skyflow import AsyncSkyflow, FileDataDeidentifyDocument
-
- client = AsyncSkyflow(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.files.deidentify_document(
- file=FileDataDeidentifyDocument(
- base_64="base64",
- data_format="pdf",
- ),
- vault_id="vault_id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._raw_client.deidentify_document(
- file=file,
- vault_id=vault_id,
- entity_types=entity_types,
- token_type=token_type,
- allow_regex=allow_regex,
- restrict_regex=restrict_regex,
- transformations=transformations,
- configuration_id=configuration_id,
- request_options=request_options,
- )
- return _response.data
-
- async def deidentify_pdf(
- self,
- *,
- file: FileDataDeidentifyPdf,
- vault_id: str,
- density: typing.Optional[int] = OMIT,
- max_resolution: typing.Optional[int] = OMIT,
- entity_types: typing.Optional[
- typing.Sequence[DeidentifyFileDocumentPdfRequestDeidentifyPdfEntityTypesItem]
- ] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> DeidentifyFileResponse:
- """
- De-identifies sensitive data from a PDF file. This operation includes options specific to PDF files.
For broader file type support, see De-identify Document and De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifyPdf
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- density : typing.Optional[int]
- Pixel density at which to process the PDF file.
-
- max_resolution : typing.Optional[int]
- Max resolution at which to process the PDF file.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileDocumentPdfRequestDeidentifyPdfEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- DeidentifyFileResponse
- OK
-
- Examples
- --------
- import asyncio
-
- from skyflow import AsyncSkyflow, FileDataDeidentifyPdf
-
- client = AsyncSkyflow(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.files.deidentify_pdf(
- file=FileDataDeidentifyPdf(
- base_64="base64",
- ),
- vault_id="vault_id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._raw_client.deidentify_pdf(
- file=file,
- vault_id=vault_id,
- density=density,
- max_resolution=max_resolution,
- entity_types=entity_types,
- token_type=token_type,
- allow_regex=allow_regex,
- restrict_regex=restrict_regex,
- transformations=transformations,
- configuration_id=configuration_id,
- request_options=request_options,
- )
- return _response.data
-
- async def deidentify_image(
- self,
- *,
- file: FileDataDeidentifyImage,
vault_id: str,
- output_processed_image: typing.Optional[bool] = OMIT,
- output_ocr_text: typing.Optional[bool] = OMIT,
- masking_method: typing.Optional[DeidentifyFileImageRequestDeidentifyImageMaskingMethod] = OMIT,
- entity_types: typing.Optional[typing.Sequence[DeidentifyFileImageRequestDeidentifyImageEntityTypesItem]] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> DeidentifyFileResponse:
- """
- De-identifies sensitive data from an image file. This operation includes options applicable to all supported image file types.
For broader file type support, see De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifyImage
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- output_processed_image : typing.Optional[bool]
- If `true`, includes processed image in the output.
-
- output_ocr_text : typing.Optional[bool]
- If `true`, includes text detected by OCR in the response.
-
- masking_method : typing.Optional[DeidentifyFileImageRequestDeidentifyImageMaskingMethod]
- Method to mask the entities in the image.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileImageRequestDeidentifyImageEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- DeidentifyFileResponse
- OK
-
- Examples
- --------
- import asyncio
-
- from skyflow import AsyncSkyflow, FileDataDeidentifyImage
-
- client = AsyncSkyflow(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.files.deidentify_image(
- file=FileDataDeidentifyImage(
- base_64="base64",
- data_format="jpg",
- ),
- vault_id="vault_id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._raw_client.deidentify_image(
- file=file,
- vault_id=vault_id,
- output_processed_image=output_processed_image,
- output_ocr_text=output_ocr_text,
- masking_method=masking_method,
- entity_types=entity_types,
- token_type=token_type,
- allow_regex=allow_regex,
- restrict_regex=restrict_regex,
- transformations=transformations,
- configuration_id=configuration_id,
- request_options=request_options,
- )
- return _response.data
-
- async def deidentify_presentation(
- self,
*,
- file: FileDataDeidentifyPresentation,
- vault_id: str,
- entity_types: typing.Optional[
- typing.Sequence[DeidentifyFileRequestDeidentifyPresentationEntityTypesItem]
- ] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
+ table_name: str,
+ column_name: str,
+ file: core.File,
+ skyflow_id: typing.Optional[str] = OMIT,
+ return_file_metadata: typing.Optional[bool] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> DeidentifyFileResponse:
+ ) -> UploadFileResponseV2:
"""
- De-identifies sensitive data from a presentation file. This operation includes options applicable to all supported presentation file types.
For broader file type support, see De-identify File.
+ Uploads a file to a new or specified record.
Parameters
----------
- file : FileDataDeidentifyPresentation
-
vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifyPresentationEntityTypesItem]]
- Entities to detect and de-identify.
- token_type : typing.Optional[TokenTypeMapping]
+ table_name : str
+ Name of the table.
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
+ column_name : str
+ Name of the column that contains the file.
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
+ file : core.File
+ See core.File for more documentation
- transformations : typing.Optional[Transformations]
+ skyflow_id : typing.Optional[str]
+ ID of the record to update.
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
+ return_file_metadata : typing.Optional[bool]
+ If `true`, returns metadata about the uploaded file.
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- DeidentifyFileResponse
+ UploadFileResponseV2
OK
Examples
--------
- import asyncio
-
- from skyflow import AsyncSkyflow, FileDataDeidentifyPresentation
+ from skyflow import SkyflowAuth
- client = AsyncSkyflow(
+ client = SkyflowAuth(
token="YOUR_TOKEN",
)
-
-
- async def main() -> None:
- await client.files.deidentify_presentation(
- file=FileDataDeidentifyPresentation(
- base_64="base64",
- data_format="ppt",
- ),
- vault_id="vault_id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._raw_client.deidentify_presentation(
- file=file,
- vault_id=vault_id,
- entity_types=entity_types,
- token_type=token_type,
- allow_regex=allow_regex,
- restrict_regex=restrict_regex,
- transformations=transformations,
- configuration_id=configuration_id,
- request_options=request_options,
- )
- return _response.data
-
- async def deidentify_spreadsheet(
- self,
- *,
- file: FileDataDeidentifySpreadsheet,
- vault_id: str,
- entity_types: typing.Optional[
- typing.Sequence[DeidentifyFileRequestDeidentifySpreadsheetEntityTypesItem]
- ] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> DeidentifyFileResponse:
- """
- De-identifies sensitive data from a spreadsheet file. This operation includes options applicable to all supported spreadsheet file types.
For broader file type support, see De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifySpreadsheet
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifySpreadsheetEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- DeidentifyFileResponse
- OK
-
- Examples
- --------
- import asyncio
-
- from skyflow import AsyncSkyflow, FileDataDeidentifySpreadsheet
-
- client = AsyncSkyflow(
- token="YOUR_TOKEN",
+ client.files.upload_file_v2(
+ vault_id="vaultID",
+ table_name="tableName",
+ column_name="columnName",
)
-
-
- async def main() -> None:
- await client.files.deidentify_spreadsheet(
- file=FileDataDeidentifySpreadsheet(
- base_64="base64",
- data_format="csv",
- ),
- vault_id="vault_id",
- )
-
-
- asyncio.run(main())
"""
- _response = await self._raw_client.deidentify_spreadsheet(
+ _response = self._raw_client.upload_file_v2(
+ vault_id,
+ table_name=table_name,
+ column_name=column_name,
file=file,
- vault_id=vault_id,
- entity_types=entity_types,
- token_type=token_type,
- allow_regex=allow_regex,
- restrict_regex=restrict_regex,
- transformations=transformations,
- configuration_id=configuration_id,
+ skyflow_id=skyflow_id,
+ return_file_metadata=return_file_metadata,
request_options=request_options,
)
return _response.data
- async def deidentify_structured_text(
- self,
- *,
- file: FileDataDeidentifyStructuredText,
- vault_id: str,
- entity_types: typing.Optional[
- typing.Sequence[DeidentifyFileRequestDeidentifyStructuredTextEntityTypesItem]
- ] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> DeidentifyFileResponse:
- """
- De-identifies sensitive data from a structured text file. This operation includes options applicable to all supported structured text file types.
For broader file type support, see De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifyStructuredText
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifyStructuredTextEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
+class AsyncFilesClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._raw_client = AsyncRawFilesClient(client_wrapper=client_wrapper)
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
+ @property
+ def with_raw_response(self) -> AsyncRawFilesClient:
+ """
+ Retrieves a raw implementation of this client that returns raw responses.
Returns
-------
- DeidentifyFileResponse
- OK
-
- Examples
- --------
- import asyncio
-
- from skyflow import AsyncSkyflow, FileDataDeidentifyStructuredText
-
- client = AsyncSkyflow(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.files.deidentify_structured_text(
- file=FileDataDeidentifyStructuredText(
- base_64="base64",
- data_format="json",
- ),
- vault_id="vault_id",
- )
-
-
- asyncio.run(main())
+ AsyncRawFilesClient
"""
- _response = await self._raw_client.deidentify_structured_text(
- file=file,
- vault_id=vault_id,
- entity_types=entity_types,
- token_type=token_type,
- allow_regex=allow_regex,
- restrict_regex=restrict_regex,
- transformations=transformations,
- configuration_id=configuration_id,
- request_options=request_options,
- )
- return _response.data
+ return self._raw_client
- async def deidentify_text(
+ async def upload_file_v2(
self,
- *,
- file: FileDataDeidentifyText,
vault_id: str,
- entity_types: typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifyTextEntityTypesItem]] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
+ *,
+ table_name: str,
+ column_name: str,
+ file: core.File,
+ skyflow_id: typing.Optional[str] = OMIT,
+ return_file_metadata: typing.Optional[bool] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> DeidentifyFileResponse:
+ ) -> UploadFileResponseV2:
"""
- De-identifies sensitive data from a text file. This operation includes options applicable to all supported image text types.
For broader file type support, see De-identify File.
+ Uploads a file to a new or specified record.
Parameters
----------
- file : FileDataDeidentifyText
-
vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifyTextEntityTypesItem]]
- Entities to detect and de-identify.
- token_type : typing.Optional[TokenTypeMapping]
+ table_name : str
+ Name of the table.
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
+ column_name : str
+ Name of the column that contains the file.
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
+ file : core.File
+ See core.File for more documentation
- transformations : typing.Optional[Transformations]
+ skyflow_id : typing.Optional[str]
+ ID of the record to update.
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
+ return_file_metadata : typing.Optional[bool]
+ If `true`, returns metadata about the uploaded file.
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- DeidentifyFileResponse
+ UploadFileResponseV2
OK
Examples
--------
import asyncio
- from skyflow import AsyncSkyflow, FileDataDeidentifyText
+ from skyflow import AsyncSkyflowAuth
- client = AsyncSkyflow(
+ client = AsyncSkyflowAuth(
token="YOUR_TOKEN",
)
async def main() -> None:
- await client.files.deidentify_text(
- file=FileDataDeidentifyText(
- base_64="base64",
- ),
- vault_id="vault_id",
+ await client.files.upload_file_v2(
+ vault_id="vaultID",
+ table_name="tableName",
+ column_name="columnName",
)
asyncio.run(main())
"""
- _response = await self._raw_client.deidentify_text(
+ _response = await self._raw_client.upload_file_v2(
+ vault_id,
+ table_name=table_name,
+ column_name=column_name,
file=file,
- vault_id=vault_id,
- entity_types=entity_types,
- token_type=token_type,
- allow_regex=allow_regex,
- restrict_regex=restrict_regex,
- transformations=transformations,
- configuration_id=configuration_id,
+ skyflow_id=skyflow_id,
+ return_file_metadata=return_file_metadata,
request_options=request_options,
)
return _response.data
-
- async def reidentify_file(
- self,
- *,
- file: FileDataReidentifyFile,
- vault_id: str,
- format: typing.Optional[Format] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> ReidentifyFileResponse:
- """
- Re-identifies tokens in a file.
-
- Parameters
- ----------
- file : FileDataReidentifyFile
-
- vault_id : str
- ID of the vault where the entities are stored.
-
- format : typing.Optional[Format]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ReidentifyFileResponse
- OK
-
- Examples
- --------
- import asyncio
-
- from skyflow import AsyncSkyflow, FileDataReidentifyFile
-
- client = AsyncSkyflow(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.files.reidentify_file(
- file=FileDataReidentifyFile(
- base_64="base64",
- data_format="txt",
- ),
- vault_id="vault_id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._raw_client.reidentify_file(
- file=file, vault_id=vault_id, format=format, request_options=request_options
- )
- return _response.data
-
- async def get_run(
- self,
- run_id: str,
- *,
- vault_id: typing.Optional[str] = None,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> DetectRunsResponse:
- """
- Returns the status of a detect run.
-
- Parameters
- ----------
- run_id : str
-
- vault_id : typing.Optional[str]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- DetectRunsResponse
- OK
-
- Examples
- --------
- import asyncio
-
- from skyflow import AsyncSkyflow
-
- client = AsyncSkyflow(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.files.get_run(
- run_id="run_id",
- vault_id="vault_id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._raw_client.get_run(run_id, vault_id=vault_id, request_options=request_options)
- return _response.data
diff --git a/skyvault/skyflow/generated/rest/files/raw_client.py b/skyvault/skyflow/generated/rest/files/raw_client.py
index 863ae5e3..c32bc035 100644
--- a/skyvault/skyflow/generated/rest/files/raw_client.py
+++ b/skyvault/skyflow/generated/rest/files/raw_client.py
@@ -3,64 +3,21 @@
import typing
from json.decoder import JSONDecodeError
+from .. import core
from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.http_response import AsyncHttpResponse, HttpResponse
-from ..core.jsonable_encoder import jsonable_encoder
+from ..core.jsonable_encoder import encode_path_param
+from ..core.parse_error import ParsingError
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
-from ..core.serialization import convert_and_respect_annotation_metadata
from ..errors.bad_request_error import BadRequestError
from ..errors.internal_server_error import InternalServerError
+from ..errors.not_found_error import NotFoundError
from ..errors.unauthorized_error import UnauthorizedError
-from ..types.deidentify_file_response import DeidentifyFileResponse
-from ..types.detect_runs_response import DetectRunsResponse
from ..types.error_response import ErrorResponse
-from ..types.file_data import FileData
-from ..types.file_data_deidentify_audio import FileDataDeidentifyAudio
-from ..types.file_data_deidentify_document import FileDataDeidentifyDocument
-from ..types.file_data_deidentify_image import FileDataDeidentifyImage
-from ..types.file_data_deidentify_pdf import FileDataDeidentifyPdf
-from ..types.file_data_deidentify_presentation import FileDataDeidentifyPresentation
-from ..types.file_data_deidentify_spreadsheet import FileDataDeidentifySpreadsheet
-from ..types.file_data_deidentify_structured_text import FileDataDeidentifyStructuredText
-from ..types.file_data_deidentify_text import FileDataDeidentifyText
-from ..types.file_data_reidentify_file import FileDataReidentifyFile
-from ..types.format import Format
-from ..types.reidentify_file_response import ReidentifyFileResponse
-from ..types.token_type_mapping import TokenTypeMapping
-from ..types.transformations import Transformations
-from .types.deidentify_file_audio_request_deidentify_audio_entity_types_item import (
- DeidentifyFileAudioRequestDeidentifyAudioEntityTypesItem,
-)
-from .types.deidentify_file_audio_request_deidentify_audio_output_transcription import (
- DeidentifyFileAudioRequestDeidentifyAudioOutputTranscription,
-)
-from .types.deidentify_file_document_pdf_request_deidentify_pdf_entity_types_item import (
- DeidentifyFileDocumentPdfRequestDeidentifyPdfEntityTypesItem,
-)
-from .types.deidentify_file_image_request_deidentify_image_entity_types_item import (
- DeidentifyFileImageRequestDeidentifyImageEntityTypesItem,
-)
-from .types.deidentify_file_image_request_deidentify_image_masking_method import (
- DeidentifyFileImageRequestDeidentifyImageMaskingMethod,
-)
-from .types.deidentify_file_request_deidentify_document_entity_types_item import (
- DeidentifyFileRequestDeidentifyDocumentEntityTypesItem,
-)
-from .types.deidentify_file_request_deidentify_presentation_entity_types_item import (
- DeidentifyFileRequestDeidentifyPresentationEntityTypesItem,
-)
-from .types.deidentify_file_request_deidentify_spreadsheet_entity_types_item import (
- DeidentifyFileRequestDeidentifySpreadsheetEntityTypesItem,
-)
-from .types.deidentify_file_request_deidentify_structured_text_entity_types_item import (
- DeidentifyFileRequestDeidentifyStructuredTextEntityTypesItem,
-)
-from .types.deidentify_file_request_deidentify_text_entity_types_item import (
- DeidentifyFileRequestDeidentifyTextEntityTypesItem,
-)
-from .types.deidentify_file_request_entity_types_item import DeidentifyFileRequestEntityTypesItem
+from ..types.upload_file_response_v2 import UploadFileResponseV2
+from pydantic import ValidationError
# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)
@@ -70,110 +27,75 @@ class RawFilesClient:
def __init__(self, *, client_wrapper: SyncClientWrapper):
self._client_wrapper = client_wrapper
- def deidentify_file(
+ def upload_file_v2(
self,
- *,
- file: FileData,
vault_id: str,
- entity_types: typing.Optional[typing.Sequence[DeidentifyFileRequestEntityTypesItem]] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
+ *,
+ table_name: str,
+ column_name: str,
+ file: core.File,
+ skyflow_id: typing.Optional[str] = OMIT,
+ return_file_metadata: typing.Optional[bool] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[DeidentifyFileResponse]:
+ ) -> HttpResponse[UploadFileResponseV2]:
"""
- De-identifies sensitive data from a file. This operation includes options applicable to all supported file types.
For more specific options, see the category-specific operations (like De-identify Document) and the file type-specific opertions (like De-identify PDF).
+ Uploads a file to a new or specified record.
Parameters
----------
- file : FileData
-
vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileRequestEntityTypesItem]]
- Entities to detect and de-identify.
- token_type : typing.Optional[TokenTypeMapping]
+ table_name : str
+ Name of the table.
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
+ column_name : str
+ Name of the column that contains the file.
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
+ file : core.File
+ See core.File for more documentation
- transformations : typing.Optional[Transformations]
+ skyflow_id : typing.Optional[str]
+ ID of the record to update.
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
+ return_file_metadata : typing.Optional[bool]
+ If `true`, returns metadata about the uploaded file.
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- HttpResponse[DeidentifyFileResponse]
+ HttpResponse[UploadFileResponseV2]
OK
"""
_response = self._client_wrapper.httpx_client.request(
- "v1/detect/deidentify/file",
+ f"v2/vaults/{encode_path_param(vault_id)}/files/upload",
method="POST",
- json={
- "file": convert_and_respect_annotation_metadata(object_=file, annotation=FileData, direction="write"),
- "vault_id": vault_id,
- "entity_types": entity_types,
- "token_type": convert_and_respect_annotation_metadata(
- object_=token_type, annotation=TokenTypeMapping, direction="write"
- ),
- "allow_regex": allow_regex,
- "restrict_regex": restrict_regex,
- "transformations": convert_and_respect_annotation_metadata(
- object_=transformations, annotation=Transformations, direction="write"
- ),
- "configuration_id": configuration_id,
+ data={
+ "tableName": table_name,
+ "columnName": column_name,
+ "skyflowID": skyflow_id,
+ "returnFileMetadata": return_file_metadata,
},
- headers={
- "content-type": "application/json",
+ files={
+ "file": file,
},
request_options=request_options,
omit=OMIT,
+ force_multipart=True,
)
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- DeidentifyFileResponse,
+ UploadFileResponseV2,
parse_obj_as(
- type_=DeidentifyFileResponse, # type: ignore
+ type_=UploadFileResponseV2, # type: ignore
object_=_response.json(),
),
)
return HttpResponse(response=_response, data=_data)
if _response.status_code == 400:
raise BadRequestError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 500:
- raise InternalServerError(
headers=dict(_response.headers),
body=typing.cast(
ErrorResponse,
@@ -183,147 +105,8 @@ def deidentify_file(
),
),
)
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
- def deidentify_audio(
- self,
- *,
- file: FileDataDeidentifyAudio,
- vault_id: str,
- output_transcription: typing.Optional[DeidentifyFileAudioRequestDeidentifyAudioOutputTranscription] = OMIT,
- output_processed_audio: typing.Optional[bool] = OMIT,
- bleep_start_padding: typing.Optional[float] = OMIT,
- bleep_stop_padding: typing.Optional[float] = OMIT,
- bleep_frequency: typing.Optional[int] = OMIT,
- bleep_gain: typing.Optional[int] = OMIT,
- entity_types: typing.Optional[typing.Sequence[DeidentifyFileAudioRequestDeidentifyAudioEntityTypesItem]] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[DeidentifyFileResponse]:
- """
- De-identifies sensitive data from an audio file. This operation includes options applicable to all supported audio file types.
For broader file type support, see De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifyAudio
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- output_transcription : typing.Optional[DeidentifyFileAudioRequestDeidentifyAudioOutputTranscription]
- Type of transcription to output.
-
- output_processed_audio : typing.Optional[bool]
- Whether to include the processed audio file in the response.
-
- bleep_start_padding : typing.Optional[float]
- Padding added to the beginning of a bleep, in seconds.
-
- bleep_stop_padding : typing.Optional[float]
- Padding added to the end of a bleep, in seconds.
-
- bleep_frequency : typing.Optional[int]
- The pitch of the bleep sound, in Hz. The higher the number, the higher the pitch.
-
- bleep_gain : typing.Optional[int]
- Relative loudness of the bleep in dB. Positive values increase its loudness, and negative values decrease it.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileAudioRequestDeidentifyAudioEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- HttpResponse[DeidentifyFileResponse]
- OK
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/detect/deidentify/file/audio",
- method="POST",
- json={
- "file": convert_and_respect_annotation_metadata(
- object_=file, annotation=FileDataDeidentifyAudio, direction="write"
- ),
- "vault_id": vault_id,
- "output_transcription": output_transcription,
- "output_processed_audio": output_processed_audio,
- "bleep_start_padding": bleep_start_padding,
- "bleep_stop_padding": bleep_stop_padding,
- "bleep_frequency": bleep_frequency,
- "bleep_gain": bleep_gain,
- "entity_types": entity_types,
- "token_type": convert_and_respect_annotation_metadata(
- object_=token_type, annotation=TokenTypeMapping, direction="write"
- ),
- "allow_regex": allow_regex,
- "restrict_regex": restrict_regex,
- "transformations": convert_and_respect_annotation_metadata(
- object_=transformations, annotation=Transformations, direction="write"
- ),
- "configuration_id": configuration_id,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- DeidentifyFileResponse,
- parse_obj_as(
- type_=DeidentifyFileResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return HttpResponse(response=_response, data=_data)
- if _response.status_code == 400:
- raise BadRequestError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
if _response.status_code == 401:
raise UnauthorizedError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 500:
- raise InternalServerError(
headers=dict(_response.headers),
body=typing.cast(
ErrorResponse,
@@ -333,117 +116,8 @@ def deidentify_audio(
),
),
)
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
- def deidentify_document(
- self,
- *,
- file: FileDataDeidentifyDocument,
- vault_id: str,
- entity_types: typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifyDocumentEntityTypesItem]] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[DeidentifyFileResponse]:
- """
- De-identifies sensitive data from a document file. This operation includes options applicable to all supported document file types.
For more specific options, see the file type-specific opertions (like De-identify PDF) where they're available. For broader file type support, see De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifyDocument
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifyDocumentEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- HttpResponse[DeidentifyFileResponse]
- OK
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/detect/deidentify/file/document",
- method="POST",
- json={
- "file": convert_and_respect_annotation_metadata(
- object_=file, annotation=FileDataDeidentifyDocument, direction="write"
- ),
- "vault_id": vault_id,
- "entity_types": entity_types,
- "token_type": convert_and_respect_annotation_metadata(
- object_=token_type, annotation=TokenTypeMapping, direction="write"
- ),
- "allow_regex": allow_regex,
- "restrict_regex": restrict_regex,
- "transformations": convert_and_respect_annotation_metadata(
- object_=transformations, annotation=Transformations, direction="write"
- ),
- "configuration_id": configuration_id,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- DeidentifyFileResponse,
- parse_obj_as(
- type_=DeidentifyFileResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return HttpResponse(response=_response, data=_data)
- if _response.status_code == 400:
- raise BadRequestError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 500:
- raise InternalServerError(
+ if _response.status_code == 404:
+ raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
ErrorResponse,
@@ -453,127 +127,6 @@ def deidentify_document(
),
),
)
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
- def deidentify_pdf(
- self,
- *,
- file: FileDataDeidentifyPdf,
- vault_id: str,
- density: typing.Optional[int] = OMIT,
- max_resolution: typing.Optional[int] = OMIT,
- entity_types: typing.Optional[
- typing.Sequence[DeidentifyFileDocumentPdfRequestDeidentifyPdfEntityTypesItem]
- ] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[DeidentifyFileResponse]:
- """
- De-identifies sensitive data from a PDF file. This operation includes options specific to PDF files.
For broader file type support, see De-identify Document and De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifyPdf
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- density : typing.Optional[int]
- Pixel density at which to process the PDF file.
-
- max_resolution : typing.Optional[int]
- Max resolution at which to process the PDF file.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileDocumentPdfRequestDeidentifyPdfEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- HttpResponse[DeidentifyFileResponse]
- OK
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/detect/deidentify/file/document/pdf",
- method="POST",
- json={
- "file": convert_and_respect_annotation_metadata(
- object_=file, annotation=FileDataDeidentifyPdf, direction="write"
- ),
- "vault_id": vault_id,
- "density": density,
- "max_resolution": max_resolution,
- "entity_types": entity_types,
- "token_type": convert_and_respect_annotation_metadata(
- object_=token_type, annotation=TokenTypeMapping, direction="write"
- ),
- "allow_regex": allow_regex,
- "restrict_regex": restrict_regex,
- "transformations": convert_and_respect_annotation_metadata(
- object_=transformations, annotation=Transformations, direction="write"
- ),
- "configuration_id": configuration_id,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- DeidentifyFileResponse,
- parse_obj_as(
- type_=DeidentifyFileResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return HttpResponse(response=_response, data=_data)
- if _response.status_code == 400:
- raise BadRequestError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
if _response.status_code == 500:
raise InternalServerError(
headers=dict(_response.headers),
@@ -588,112 +141,91 @@ def deidentify_pdf(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
- def deidentify_image(
+
+class AsyncRawFilesClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def upload_file_v2(
self,
- *,
- file: FileDataDeidentifyImage,
vault_id: str,
- output_processed_image: typing.Optional[bool] = OMIT,
- output_ocr_text: typing.Optional[bool] = OMIT,
- masking_method: typing.Optional[DeidentifyFileImageRequestDeidentifyImageMaskingMethod] = OMIT,
- entity_types: typing.Optional[typing.Sequence[DeidentifyFileImageRequestDeidentifyImageEntityTypesItem]] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
+ *,
+ table_name: str,
+ column_name: str,
+ file: core.File,
+ skyflow_id: typing.Optional[str] = OMIT,
+ return_file_metadata: typing.Optional[bool] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[DeidentifyFileResponse]:
+ ) -> AsyncHttpResponse[UploadFileResponseV2]:
"""
- De-identifies sensitive data from an image file. This operation includes options applicable to all supported image file types.
For broader file type support, see De-identify File.
+ Uploads a file to a new or specified record.
Parameters
----------
- file : FileDataDeidentifyImage
-
vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- output_processed_image : typing.Optional[bool]
- If `true`, includes processed image in the output.
-
- output_ocr_text : typing.Optional[bool]
- If `true`, includes text detected by OCR in the response.
- masking_method : typing.Optional[DeidentifyFileImageRequestDeidentifyImageMaskingMethod]
- Method to mask the entities in the image.
+ table_name : str
+ Name of the table.
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileImageRequestDeidentifyImageEntityTypesItem]]
- Entities to detect and de-identify.
+ column_name : str
+ Name of the column that contains the file.
- token_type : typing.Optional[TokenTypeMapping]
+ file : core.File
+ See core.File for more documentation
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
+ skyflow_id : typing.Optional[str]
+ ID of the record to update.
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
+ return_file_metadata : typing.Optional[bool]
+ If `true`, returns metadata about the uploaded file.
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- HttpResponse[DeidentifyFileResponse]
+ AsyncHttpResponse[UploadFileResponseV2]
OK
"""
- _response = self._client_wrapper.httpx_client.request(
- "v1/detect/deidentify/file/image",
+ _response = await self._client_wrapper.httpx_client.request(
+ f"v2/vaults/{encode_path_param(vault_id)}/files/upload",
method="POST",
- json={
- "file": convert_and_respect_annotation_metadata(
- object_=file, annotation=FileDataDeidentifyImage, direction="write"
- ),
- "vault_id": vault_id,
- "output_processed_image": output_processed_image,
- "output_ocr_text": output_ocr_text,
- "masking_method": masking_method,
- "entity_types": entity_types,
- "token_type": convert_and_respect_annotation_metadata(
- object_=token_type, annotation=TokenTypeMapping, direction="write"
- ),
- "allow_regex": allow_regex,
- "restrict_regex": restrict_regex,
- "transformations": convert_and_respect_annotation_metadata(
- object_=transformations, annotation=Transformations, direction="write"
- ),
- "configuration_id": configuration_id,
+ data={
+ "tableName": table_name,
+ "columnName": column_name,
+ "skyflowID": skyflow_id,
+ "returnFileMetadata": return_file_metadata,
},
- headers={
- "content-type": "application/json",
+ files={
+ "file": file,
},
request_options=request_options,
omit=OMIT,
+ force_multipart=True,
)
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- DeidentifyFileResponse,
+ UploadFileResponseV2,
parse_obj_as(
- type_=DeidentifyFileResponse, # type: ignore
+ type_=UploadFileResponseV2, # type: ignore
object_=_response.json(),
),
)
- return HttpResponse(response=_response, data=_data)
+ return AsyncHttpResponse(response=_response, data=_data)
if _response.status_code == 400:
raise BadRequestError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -702,15 +234,15 @@ def deidentify_image(
raise UnauthorizedError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
)
- if _response.status_code == 500:
- raise InternalServerError(
+ if _response.status_code == 404:
+ raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
ErrorResponse,
@@ -720,1971 +252,6 @@ def deidentify_image(
),
),
)
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
- def deidentify_presentation(
- self,
- *,
- file: FileDataDeidentifyPresentation,
- vault_id: str,
- entity_types: typing.Optional[
- typing.Sequence[DeidentifyFileRequestDeidentifyPresentationEntityTypesItem]
- ] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[DeidentifyFileResponse]:
- """
- De-identifies sensitive data from a presentation file. This operation includes options applicable to all supported presentation file types.
For broader file type support, see De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifyPresentation
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifyPresentationEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- HttpResponse[DeidentifyFileResponse]
- OK
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/detect/deidentify/file/presentation",
- method="POST",
- json={
- "file": convert_and_respect_annotation_metadata(
- object_=file, annotation=FileDataDeidentifyPresentation, direction="write"
- ),
- "vault_id": vault_id,
- "entity_types": entity_types,
- "token_type": convert_and_respect_annotation_metadata(
- object_=token_type, annotation=TokenTypeMapping, direction="write"
- ),
- "allow_regex": allow_regex,
- "restrict_regex": restrict_regex,
- "transformations": convert_and_respect_annotation_metadata(
- object_=transformations, annotation=Transformations, direction="write"
- ),
- "configuration_id": configuration_id,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- DeidentifyFileResponse,
- parse_obj_as(
- type_=DeidentifyFileResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return HttpResponse(response=_response, data=_data)
- if _response.status_code == 400:
- raise BadRequestError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 500:
- raise InternalServerError(
- headers=dict(_response.headers),
- body=typing.cast(
- ErrorResponse,
- parse_obj_as(
- type_=ErrorResponse, # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
- def deidentify_spreadsheet(
- self,
- *,
- file: FileDataDeidentifySpreadsheet,
- vault_id: str,
- entity_types: typing.Optional[
- typing.Sequence[DeidentifyFileRequestDeidentifySpreadsheetEntityTypesItem]
- ] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[DeidentifyFileResponse]:
- """
- De-identifies sensitive data from a spreadsheet file. This operation includes options applicable to all supported spreadsheet file types.
For broader file type support, see De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifySpreadsheet
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifySpreadsheetEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- HttpResponse[DeidentifyFileResponse]
- OK
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/detect/deidentify/file/spreadsheet",
- method="POST",
- json={
- "file": convert_and_respect_annotation_metadata(
- object_=file, annotation=FileDataDeidentifySpreadsheet, direction="write"
- ),
- "vault_id": vault_id,
- "entity_types": entity_types,
- "token_type": convert_and_respect_annotation_metadata(
- object_=token_type, annotation=TokenTypeMapping, direction="write"
- ),
- "allow_regex": allow_regex,
- "restrict_regex": restrict_regex,
- "transformations": convert_and_respect_annotation_metadata(
- object_=transformations, annotation=Transformations, direction="write"
- ),
- "configuration_id": configuration_id,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- DeidentifyFileResponse,
- parse_obj_as(
- type_=DeidentifyFileResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return HttpResponse(response=_response, data=_data)
- if _response.status_code == 400:
- raise BadRequestError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 500:
- raise InternalServerError(
- headers=dict(_response.headers),
- body=typing.cast(
- ErrorResponse,
- parse_obj_as(
- type_=ErrorResponse, # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
- def deidentify_structured_text(
- self,
- *,
- file: FileDataDeidentifyStructuredText,
- vault_id: str,
- entity_types: typing.Optional[
- typing.Sequence[DeidentifyFileRequestDeidentifyStructuredTextEntityTypesItem]
- ] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[DeidentifyFileResponse]:
- """
- De-identifies sensitive data from a structured text file. This operation includes options applicable to all supported structured text file types.
For broader file type support, see De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifyStructuredText
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifyStructuredTextEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- HttpResponse[DeidentifyFileResponse]
- OK
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/detect/deidentify/file/structured_text",
- method="POST",
- json={
- "file": convert_and_respect_annotation_metadata(
- object_=file, annotation=FileDataDeidentifyStructuredText, direction="write"
- ),
- "vault_id": vault_id,
- "entity_types": entity_types,
- "token_type": convert_and_respect_annotation_metadata(
- object_=token_type, annotation=TokenTypeMapping, direction="write"
- ),
- "allow_regex": allow_regex,
- "restrict_regex": restrict_regex,
- "transformations": convert_and_respect_annotation_metadata(
- object_=transformations, annotation=Transformations, direction="write"
- ),
- "configuration_id": configuration_id,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- DeidentifyFileResponse,
- parse_obj_as(
- type_=DeidentifyFileResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return HttpResponse(response=_response, data=_data)
- if _response.status_code == 400:
- raise BadRequestError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 500:
- raise InternalServerError(
- headers=dict(_response.headers),
- body=typing.cast(
- ErrorResponse,
- parse_obj_as(
- type_=ErrorResponse, # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
- def deidentify_text(
- self,
- *,
- file: FileDataDeidentifyText,
- vault_id: str,
- entity_types: typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifyTextEntityTypesItem]] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[DeidentifyFileResponse]:
- """
- De-identifies sensitive data from a text file. This operation includes options applicable to all supported image text types.
For broader file type support, see De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifyText
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifyTextEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- HttpResponse[DeidentifyFileResponse]
- OK
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/detect/deidentify/file/text",
- method="POST",
- json={
- "file": convert_and_respect_annotation_metadata(
- object_=file, annotation=FileDataDeidentifyText, direction="write"
- ),
- "vault_id": vault_id,
- "entity_types": entity_types,
- "token_type": convert_and_respect_annotation_metadata(
- object_=token_type, annotation=TokenTypeMapping, direction="write"
- ),
- "allow_regex": allow_regex,
- "restrict_regex": restrict_regex,
- "transformations": convert_and_respect_annotation_metadata(
- object_=transformations, annotation=Transformations, direction="write"
- ),
- "configuration_id": configuration_id,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- DeidentifyFileResponse,
- parse_obj_as(
- type_=DeidentifyFileResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return HttpResponse(response=_response, data=_data)
- if _response.status_code == 400:
- raise BadRequestError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 500:
- raise InternalServerError(
- headers=dict(_response.headers),
- body=typing.cast(
- ErrorResponse,
- parse_obj_as(
- type_=ErrorResponse, # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
- def reidentify_file(
- self,
- *,
- file: FileDataReidentifyFile,
- vault_id: str,
- format: typing.Optional[Format] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[ReidentifyFileResponse]:
- """
- Re-identifies tokens in a file.
-
- Parameters
- ----------
- file : FileDataReidentifyFile
-
- vault_id : str
- ID of the vault where the entities are stored.
-
- format : typing.Optional[Format]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- HttpResponse[ReidentifyFileResponse]
- OK
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/detect/reidentify/file",
- method="POST",
- json={
- "file": convert_and_respect_annotation_metadata(
- object_=file, annotation=FileDataReidentifyFile, direction="write"
- ),
- "vault_id": vault_id,
- "format": convert_and_respect_annotation_metadata(object_=format, annotation=Format, direction="write"),
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- ReidentifyFileResponse,
- parse_obj_as(
- type_=ReidentifyFileResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return HttpResponse(response=_response, data=_data)
- if _response.status_code == 400:
- raise BadRequestError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 500:
- raise InternalServerError(
- headers=dict(_response.headers),
- body=typing.cast(
- ErrorResponse,
- parse_obj_as(
- type_=ErrorResponse, # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
- def get_run(
- self,
- run_id: str,
- *,
- vault_id: typing.Optional[str] = None,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[DetectRunsResponse]:
- """
- Returns the status of a detect run.
-
- Parameters
- ----------
- run_id : str
-
- vault_id : typing.Optional[str]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- HttpResponse[DetectRunsResponse]
- OK
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/detect/runs/{jsonable_encoder(run_id)}",
- method="GET",
- params={
- "vault_id": vault_id,
- },
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- DetectRunsResponse,
- parse_obj_as(
- type_=DetectRunsResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return HttpResponse(response=_response, data=_data)
- if _response.status_code == 400:
- raise BadRequestError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 500:
- raise InternalServerError(
- headers=dict(_response.headers),
- body=typing.cast(
- ErrorResponse,
- parse_obj_as(
- type_=ErrorResponse, # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
-
-class AsyncRawFilesClient:
- def __init__(self, *, client_wrapper: AsyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- async def deidentify_file(
- self,
- *,
- file: FileData,
- vault_id: str,
- entity_types: typing.Optional[typing.Sequence[DeidentifyFileRequestEntityTypesItem]] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[DeidentifyFileResponse]:
- """
- De-identifies sensitive data from a file. This operation includes options applicable to all supported file types.
For more specific options, see the category-specific operations (like De-identify Document) and the file type-specific opertions (like De-identify PDF).
-
- Parameters
- ----------
- file : FileData
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileRequestEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AsyncHttpResponse[DeidentifyFileResponse]
- OK
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/detect/deidentify/file",
- method="POST",
- json={
- "file": convert_and_respect_annotation_metadata(object_=file, annotation=FileData, direction="write"),
- "vault_id": vault_id,
- "entity_types": entity_types,
- "token_type": convert_and_respect_annotation_metadata(
- object_=token_type, annotation=TokenTypeMapping, direction="write"
- ),
- "allow_regex": allow_regex,
- "restrict_regex": restrict_regex,
- "transformations": convert_and_respect_annotation_metadata(
- object_=transformations, annotation=Transformations, direction="write"
- ),
- "configuration_id": configuration_id,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- DeidentifyFileResponse,
- parse_obj_as(
- type_=DeidentifyFileResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return AsyncHttpResponse(response=_response, data=_data)
- if _response.status_code == 400:
- raise BadRequestError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 500:
- raise InternalServerError(
- headers=dict(_response.headers),
- body=typing.cast(
- ErrorResponse,
- parse_obj_as(
- type_=ErrorResponse, # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
- async def deidentify_audio(
- self,
- *,
- file: FileDataDeidentifyAudio,
- vault_id: str,
- output_transcription: typing.Optional[DeidentifyFileAudioRequestDeidentifyAudioOutputTranscription] = OMIT,
- output_processed_audio: typing.Optional[bool] = OMIT,
- bleep_start_padding: typing.Optional[float] = OMIT,
- bleep_stop_padding: typing.Optional[float] = OMIT,
- bleep_frequency: typing.Optional[int] = OMIT,
- bleep_gain: typing.Optional[int] = OMIT,
- entity_types: typing.Optional[typing.Sequence[DeidentifyFileAudioRequestDeidentifyAudioEntityTypesItem]] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[DeidentifyFileResponse]:
- """
- De-identifies sensitive data from an audio file. This operation includes options applicable to all supported audio file types.
For broader file type support, see De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifyAudio
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- output_transcription : typing.Optional[DeidentifyFileAudioRequestDeidentifyAudioOutputTranscription]
- Type of transcription to output.
-
- output_processed_audio : typing.Optional[bool]
- Whether to include the processed audio file in the response.
-
- bleep_start_padding : typing.Optional[float]
- Padding added to the beginning of a bleep, in seconds.
-
- bleep_stop_padding : typing.Optional[float]
- Padding added to the end of a bleep, in seconds.
-
- bleep_frequency : typing.Optional[int]
- The pitch of the bleep sound, in Hz. The higher the number, the higher the pitch.
-
- bleep_gain : typing.Optional[int]
- Relative loudness of the bleep in dB. Positive values increase its loudness, and negative values decrease it.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileAudioRequestDeidentifyAudioEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AsyncHttpResponse[DeidentifyFileResponse]
- OK
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/detect/deidentify/file/audio",
- method="POST",
- json={
- "file": convert_and_respect_annotation_metadata(
- object_=file, annotation=FileDataDeidentifyAudio, direction="write"
- ),
- "vault_id": vault_id,
- "output_transcription": output_transcription,
- "output_processed_audio": output_processed_audio,
- "bleep_start_padding": bleep_start_padding,
- "bleep_stop_padding": bleep_stop_padding,
- "bleep_frequency": bleep_frequency,
- "bleep_gain": bleep_gain,
- "entity_types": entity_types,
- "token_type": convert_and_respect_annotation_metadata(
- object_=token_type, annotation=TokenTypeMapping, direction="write"
- ),
- "allow_regex": allow_regex,
- "restrict_regex": restrict_regex,
- "transformations": convert_and_respect_annotation_metadata(
- object_=transformations, annotation=Transformations, direction="write"
- ),
- "configuration_id": configuration_id,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- DeidentifyFileResponse,
- parse_obj_as(
- type_=DeidentifyFileResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return AsyncHttpResponse(response=_response, data=_data)
- if _response.status_code == 400:
- raise BadRequestError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 500:
- raise InternalServerError(
- headers=dict(_response.headers),
- body=typing.cast(
- ErrorResponse,
- parse_obj_as(
- type_=ErrorResponse, # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
- async def deidentify_document(
- self,
- *,
- file: FileDataDeidentifyDocument,
- vault_id: str,
- entity_types: typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifyDocumentEntityTypesItem]] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[DeidentifyFileResponse]:
- """
- De-identifies sensitive data from a document file. This operation includes options applicable to all supported document file types.
For more specific options, see the file type-specific opertions (like De-identify PDF) where they're available. For broader file type support, see De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifyDocument
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifyDocumentEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AsyncHttpResponse[DeidentifyFileResponse]
- OK
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/detect/deidentify/file/document",
- method="POST",
- json={
- "file": convert_and_respect_annotation_metadata(
- object_=file, annotation=FileDataDeidentifyDocument, direction="write"
- ),
- "vault_id": vault_id,
- "entity_types": entity_types,
- "token_type": convert_and_respect_annotation_metadata(
- object_=token_type, annotation=TokenTypeMapping, direction="write"
- ),
- "allow_regex": allow_regex,
- "restrict_regex": restrict_regex,
- "transformations": convert_and_respect_annotation_metadata(
- object_=transformations, annotation=Transformations, direction="write"
- ),
- "configuration_id": configuration_id,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- DeidentifyFileResponse,
- parse_obj_as(
- type_=DeidentifyFileResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return AsyncHttpResponse(response=_response, data=_data)
- if _response.status_code == 400:
- raise BadRequestError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 500:
- raise InternalServerError(
- headers=dict(_response.headers),
- body=typing.cast(
- ErrorResponse,
- parse_obj_as(
- type_=ErrorResponse, # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
- async def deidentify_pdf(
- self,
- *,
- file: FileDataDeidentifyPdf,
- vault_id: str,
- density: typing.Optional[int] = OMIT,
- max_resolution: typing.Optional[int] = OMIT,
- entity_types: typing.Optional[
- typing.Sequence[DeidentifyFileDocumentPdfRequestDeidentifyPdfEntityTypesItem]
- ] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[DeidentifyFileResponse]:
- """
- De-identifies sensitive data from a PDF file. This operation includes options specific to PDF files.
For broader file type support, see De-identify Document and De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifyPdf
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- density : typing.Optional[int]
- Pixel density at which to process the PDF file.
-
- max_resolution : typing.Optional[int]
- Max resolution at which to process the PDF file.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileDocumentPdfRequestDeidentifyPdfEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AsyncHttpResponse[DeidentifyFileResponse]
- OK
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/detect/deidentify/file/document/pdf",
- method="POST",
- json={
- "file": convert_and_respect_annotation_metadata(
- object_=file, annotation=FileDataDeidentifyPdf, direction="write"
- ),
- "vault_id": vault_id,
- "density": density,
- "max_resolution": max_resolution,
- "entity_types": entity_types,
- "token_type": convert_and_respect_annotation_metadata(
- object_=token_type, annotation=TokenTypeMapping, direction="write"
- ),
- "allow_regex": allow_regex,
- "restrict_regex": restrict_regex,
- "transformations": convert_and_respect_annotation_metadata(
- object_=transformations, annotation=Transformations, direction="write"
- ),
- "configuration_id": configuration_id,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- DeidentifyFileResponse,
- parse_obj_as(
- type_=DeidentifyFileResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return AsyncHttpResponse(response=_response, data=_data)
- if _response.status_code == 400:
- raise BadRequestError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 500:
- raise InternalServerError(
- headers=dict(_response.headers),
- body=typing.cast(
- ErrorResponse,
- parse_obj_as(
- type_=ErrorResponse, # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
- async def deidentify_image(
- self,
- *,
- file: FileDataDeidentifyImage,
- vault_id: str,
- output_processed_image: typing.Optional[bool] = OMIT,
- output_ocr_text: typing.Optional[bool] = OMIT,
- masking_method: typing.Optional[DeidentifyFileImageRequestDeidentifyImageMaskingMethod] = OMIT,
- entity_types: typing.Optional[typing.Sequence[DeidentifyFileImageRequestDeidentifyImageEntityTypesItem]] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[DeidentifyFileResponse]:
- """
- De-identifies sensitive data from an image file. This operation includes options applicable to all supported image file types.
For broader file type support, see De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifyImage
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- output_processed_image : typing.Optional[bool]
- If `true`, includes processed image in the output.
-
- output_ocr_text : typing.Optional[bool]
- If `true`, includes text detected by OCR in the response.
-
- masking_method : typing.Optional[DeidentifyFileImageRequestDeidentifyImageMaskingMethod]
- Method to mask the entities in the image.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileImageRequestDeidentifyImageEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AsyncHttpResponse[DeidentifyFileResponse]
- OK
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/detect/deidentify/file/image",
- method="POST",
- json={
- "file": convert_and_respect_annotation_metadata(
- object_=file, annotation=FileDataDeidentifyImage, direction="write"
- ),
- "vault_id": vault_id,
- "output_processed_image": output_processed_image,
- "output_ocr_text": output_ocr_text,
- "masking_method": masking_method,
- "entity_types": entity_types,
- "token_type": convert_and_respect_annotation_metadata(
- object_=token_type, annotation=TokenTypeMapping, direction="write"
- ),
- "allow_regex": allow_regex,
- "restrict_regex": restrict_regex,
- "transformations": convert_and_respect_annotation_metadata(
- object_=transformations, annotation=Transformations, direction="write"
- ),
- "configuration_id": configuration_id,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- DeidentifyFileResponse,
- parse_obj_as(
- type_=DeidentifyFileResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return AsyncHttpResponse(response=_response, data=_data)
- if _response.status_code == 400:
- raise BadRequestError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 500:
- raise InternalServerError(
- headers=dict(_response.headers),
- body=typing.cast(
- ErrorResponse,
- parse_obj_as(
- type_=ErrorResponse, # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
- async def deidentify_presentation(
- self,
- *,
- file: FileDataDeidentifyPresentation,
- vault_id: str,
- entity_types: typing.Optional[
- typing.Sequence[DeidentifyFileRequestDeidentifyPresentationEntityTypesItem]
- ] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[DeidentifyFileResponse]:
- """
- De-identifies sensitive data from a presentation file. This operation includes options applicable to all supported presentation file types.
For broader file type support, see De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifyPresentation
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifyPresentationEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AsyncHttpResponse[DeidentifyFileResponse]
- OK
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/detect/deidentify/file/presentation",
- method="POST",
- json={
- "file": convert_and_respect_annotation_metadata(
- object_=file, annotation=FileDataDeidentifyPresentation, direction="write"
- ),
- "vault_id": vault_id,
- "entity_types": entity_types,
- "token_type": convert_and_respect_annotation_metadata(
- object_=token_type, annotation=TokenTypeMapping, direction="write"
- ),
- "allow_regex": allow_regex,
- "restrict_regex": restrict_regex,
- "transformations": convert_and_respect_annotation_metadata(
- object_=transformations, annotation=Transformations, direction="write"
- ),
- "configuration_id": configuration_id,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- DeidentifyFileResponse,
- parse_obj_as(
- type_=DeidentifyFileResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return AsyncHttpResponse(response=_response, data=_data)
- if _response.status_code == 400:
- raise BadRequestError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 500:
- raise InternalServerError(
- headers=dict(_response.headers),
- body=typing.cast(
- ErrorResponse,
- parse_obj_as(
- type_=ErrorResponse, # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
- async def deidentify_spreadsheet(
- self,
- *,
- file: FileDataDeidentifySpreadsheet,
- vault_id: str,
- entity_types: typing.Optional[
- typing.Sequence[DeidentifyFileRequestDeidentifySpreadsheetEntityTypesItem]
- ] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[DeidentifyFileResponse]:
- """
- De-identifies sensitive data from a spreadsheet file. This operation includes options applicable to all supported spreadsheet file types.
For broader file type support, see De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifySpreadsheet
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifySpreadsheetEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AsyncHttpResponse[DeidentifyFileResponse]
- OK
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/detect/deidentify/file/spreadsheet",
- method="POST",
- json={
- "file": convert_and_respect_annotation_metadata(
- object_=file, annotation=FileDataDeidentifySpreadsheet, direction="write"
- ),
- "vault_id": vault_id,
- "entity_types": entity_types,
- "token_type": convert_and_respect_annotation_metadata(
- object_=token_type, annotation=TokenTypeMapping, direction="write"
- ),
- "allow_regex": allow_regex,
- "restrict_regex": restrict_regex,
- "transformations": convert_and_respect_annotation_metadata(
- object_=transformations, annotation=Transformations, direction="write"
- ),
- "configuration_id": configuration_id,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- DeidentifyFileResponse,
- parse_obj_as(
- type_=DeidentifyFileResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return AsyncHttpResponse(response=_response, data=_data)
- if _response.status_code == 400:
- raise BadRequestError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 500:
- raise InternalServerError(
- headers=dict(_response.headers),
- body=typing.cast(
- ErrorResponse,
- parse_obj_as(
- type_=ErrorResponse, # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
- async def deidentify_structured_text(
- self,
- *,
- file: FileDataDeidentifyStructuredText,
- vault_id: str,
- entity_types: typing.Optional[
- typing.Sequence[DeidentifyFileRequestDeidentifyStructuredTextEntityTypesItem]
- ] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[DeidentifyFileResponse]:
- """
- De-identifies sensitive data from a structured text file. This operation includes options applicable to all supported structured text file types.
For broader file type support, see De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifyStructuredText
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifyStructuredTextEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AsyncHttpResponse[DeidentifyFileResponse]
- OK
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/detect/deidentify/file/structured_text",
- method="POST",
- json={
- "file": convert_and_respect_annotation_metadata(
- object_=file, annotation=FileDataDeidentifyStructuredText, direction="write"
- ),
- "vault_id": vault_id,
- "entity_types": entity_types,
- "token_type": convert_and_respect_annotation_metadata(
- object_=token_type, annotation=TokenTypeMapping, direction="write"
- ),
- "allow_regex": allow_regex,
- "restrict_regex": restrict_regex,
- "transformations": convert_and_respect_annotation_metadata(
- object_=transformations, annotation=Transformations, direction="write"
- ),
- "configuration_id": configuration_id,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- DeidentifyFileResponse,
- parse_obj_as(
- type_=DeidentifyFileResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return AsyncHttpResponse(response=_response, data=_data)
- if _response.status_code == 400:
- raise BadRequestError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 500:
- raise InternalServerError(
- headers=dict(_response.headers),
- body=typing.cast(
- ErrorResponse,
- parse_obj_as(
- type_=ErrorResponse, # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
- async def deidentify_text(
- self,
- *,
- file: FileDataDeidentifyText,
- vault_id: str,
- entity_types: typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifyTextEntityTypesItem]] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[DeidentifyFileResponse]:
- """
- De-identifies sensitive data from a text file. This operation includes options applicable to all supported image text types.
For broader file type support, see De-identify File.
-
- Parameters
- ----------
- file : FileDataDeidentifyText
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyFileRequestDeidentifyTextEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AsyncHttpResponse[DeidentifyFileResponse]
- OK
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/detect/deidentify/file/text",
- method="POST",
- json={
- "file": convert_and_respect_annotation_metadata(
- object_=file, annotation=FileDataDeidentifyText, direction="write"
- ),
- "vault_id": vault_id,
- "entity_types": entity_types,
- "token_type": convert_and_respect_annotation_metadata(
- object_=token_type, annotation=TokenTypeMapping, direction="write"
- ),
- "allow_regex": allow_regex,
- "restrict_regex": restrict_regex,
- "transformations": convert_and_respect_annotation_metadata(
- object_=transformations, annotation=Transformations, direction="write"
- ),
- "configuration_id": configuration_id,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- DeidentifyFileResponse,
- parse_obj_as(
- type_=DeidentifyFileResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return AsyncHttpResponse(response=_response, data=_data)
- if _response.status_code == 400:
- raise BadRequestError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 500:
- raise InternalServerError(
- headers=dict(_response.headers),
- body=typing.cast(
- ErrorResponse,
- parse_obj_as(
- type_=ErrorResponse, # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
- async def reidentify_file(
- self,
- *,
- file: FileDataReidentifyFile,
- vault_id: str,
- format: typing.Optional[Format] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[ReidentifyFileResponse]:
- """
- Re-identifies tokens in a file.
-
- Parameters
- ----------
- file : FileDataReidentifyFile
-
- vault_id : str
- ID of the vault where the entities are stored.
-
- format : typing.Optional[Format]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AsyncHttpResponse[ReidentifyFileResponse]
- OK
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/detect/reidentify/file",
- method="POST",
- json={
- "file": convert_and_respect_annotation_metadata(
- object_=file, annotation=FileDataReidentifyFile, direction="write"
- ),
- "vault_id": vault_id,
- "format": convert_and_respect_annotation_metadata(object_=format, annotation=Format, direction="write"),
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- ReidentifyFileResponse,
- parse_obj_as(
- type_=ReidentifyFileResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return AsyncHttpResponse(response=_response, data=_data)
- if _response.status_code == 400:
- raise BadRequestError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 500:
- raise InternalServerError(
- headers=dict(_response.headers),
- body=typing.cast(
- ErrorResponse,
- parse_obj_as(
- type_=ErrorResponse, # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
- async def get_run(
- self,
- run_id: str,
- *,
- vault_id: typing.Optional[str] = None,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[DetectRunsResponse]:
- """
- Returns the status of a detect run.
-
- Parameters
- ----------
- run_id : str
-
- vault_id : typing.Optional[str]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AsyncHttpResponse[DetectRunsResponse]
- OK
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/detect/runs/{jsonable_encoder(run_id)}",
- method="GET",
- params={
- "vault_id": vault_id,
- },
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- DetectRunsResponse,
- parse_obj_as(
- type_=DetectRunsResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return AsyncHttpResponse(response=_response, data=_data)
- if _response.status_code == 400:
- raise BadRequestError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
if _response.status_code == 500:
raise InternalServerError(
headers=dict(_response.headers),
@@ -2699,4 +266,8 @@ async def get_run(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/skyvault/skyflow/generated/rest/files/types/__init__.py b/skyvault/skyflow/generated/rest/files/types/__init__.py
deleted file mode 100644
index 5ff54d96..00000000
--- a/skyvault/skyflow/generated/rest/files/types/__init__.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-# isort: skip_file
-
-from .deidentify_file_audio_request_deidentify_audio_entity_types_item import (
- DeidentifyFileAudioRequestDeidentifyAudioEntityTypesItem,
-)
-from .deidentify_file_audio_request_deidentify_audio_output_transcription import (
- DeidentifyFileAudioRequestDeidentifyAudioOutputTranscription,
-)
-from .deidentify_file_document_pdf_request_deidentify_pdf_entity_types_item import (
- DeidentifyFileDocumentPdfRequestDeidentifyPdfEntityTypesItem,
-)
-from .deidentify_file_image_request_deidentify_image_entity_types_item import (
- DeidentifyFileImageRequestDeidentifyImageEntityTypesItem,
-)
-from .deidentify_file_image_request_deidentify_image_masking_method import (
- DeidentifyFileImageRequestDeidentifyImageMaskingMethod,
-)
-from .deidentify_file_request_deidentify_document_entity_types_item import (
- DeidentifyFileRequestDeidentifyDocumentEntityTypesItem,
-)
-from .deidentify_file_request_deidentify_presentation_entity_types_item import (
- DeidentifyFileRequestDeidentifyPresentationEntityTypesItem,
-)
-from .deidentify_file_request_deidentify_spreadsheet_entity_types_item import (
- DeidentifyFileRequestDeidentifySpreadsheetEntityTypesItem,
-)
-from .deidentify_file_request_deidentify_structured_text_entity_types_item import (
- DeidentifyFileRequestDeidentifyStructuredTextEntityTypesItem,
-)
-from .deidentify_file_request_deidentify_text_entity_types_item import (
- DeidentifyFileRequestDeidentifyTextEntityTypesItem,
-)
-from .deidentify_file_request_entity_types_item import DeidentifyFileRequestEntityTypesItem
-
-__all__ = [
- "DeidentifyFileAudioRequestDeidentifyAudioEntityTypesItem",
- "DeidentifyFileAudioRequestDeidentifyAudioOutputTranscription",
- "DeidentifyFileDocumentPdfRequestDeidentifyPdfEntityTypesItem",
- "DeidentifyFileImageRequestDeidentifyImageEntityTypesItem",
- "DeidentifyFileImageRequestDeidentifyImageMaskingMethod",
- "DeidentifyFileRequestDeidentifyDocumentEntityTypesItem",
- "DeidentifyFileRequestDeidentifyPresentationEntityTypesItem",
- "DeidentifyFileRequestDeidentifySpreadsheetEntityTypesItem",
- "DeidentifyFileRequestDeidentifyStructuredTextEntityTypesItem",
- "DeidentifyFileRequestDeidentifyTextEntityTypesItem",
- "DeidentifyFileRequestEntityTypesItem",
-]
diff --git a/skyvault/skyflow/generated/rest/files/types/deidentify_file_audio_request_deidentify_audio_entity_types_item.py b/skyvault/skyflow/generated/rest/files/types/deidentify_file_audio_request_deidentify_audio_entity_types_item.py
deleted file mode 100644
index b22a177a..00000000
--- a/skyvault/skyflow/generated/rest/files/types/deidentify_file_audio_request_deidentify_audio_entity_types_item.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-DeidentifyFileAudioRequestDeidentifyAudioEntityTypesItem = typing.Union[
- typing.Literal[
- "age",
- "bank_account",
- "credit_card",
- "credit_card_expiration",
- "cvv",
- "date",
- "date_interval",
- "dob",
- "driver_license",
- "email_address",
- "healthcare_number",
- "ip_address",
- "location",
- "name",
- "numerical_pii",
- "phone_number",
- "ssn",
- "url",
- "vehicle_id",
- "medical_code",
- "name_family",
- "name_given",
- "account_number",
- "event",
- "filename",
- "gender",
- "language",
- "location_address",
- "location_city",
- "location_coordinate",
- "location_country",
- "location_state",
- "location_zip",
- "marital_status",
- "money",
- "name_medical_professional",
- "occupation",
- "organization",
- "organization_medical_facility",
- "origin",
- "passport_number",
- "password",
- "physical_attribute",
- "political_affiliation",
- "religion",
- "time",
- "username",
- "zodiac_sign",
- "blood_type",
- "condition",
- "dose",
- "drug",
- "injury",
- "medical_process",
- "statistics",
- "routing_number",
- "corporate_action",
- "financial_metric",
- "product",
- "trend",
- "duration",
- "location_address_street",
- "all",
- "sexuality",
- "effect",
- "project",
- "organization_id",
- "day",
- "month",
- "year",
- ],
- typing.Any,
-]
diff --git a/skyvault/skyflow/generated/rest/files/types/deidentify_file_audio_request_deidentify_audio_output_transcription.py b/skyvault/skyflow/generated/rest/files/types/deidentify_file_audio_request_deidentify_audio_output_transcription.py
deleted file mode 100644
index 957cee86..00000000
--- a/skyvault/skyflow/generated/rest/files/types/deidentify_file_audio_request_deidentify_audio_output_transcription.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-DeidentifyFileAudioRequestDeidentifyAudioOutputTranscription = typing.Union[
- typing.Literal[
- "transcription", "medical_transcription", "diarized_transcription", "medical_diarized_transcription"
- ],
- typing.Any,
-]
diff --git a/skyvault/skyflow/generated/rest/files/types/deidentify_file_document_pdf_request_deidentify_pdf_entity_types_item.py b/skyvault/skyflow/generated/rest/files/types/deidentify_file_document_pdf_request_deidentify_pdf_entity_types_item.py
deleted file mode 100644
index d8469e74..00000000
--- a/skyvault/skyflow/generated/rest/files/types/deidentify_file_document_pdf_request_deidentify_pdf_entity_types_item.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-DeidentifyFileDocumentPdfRequestDeidentifyPdfEntityTypesItem = typing.Union[
- typing.Literal[
- "age",
- "bank_account",
- "credit_card",
- "credit_card_expiration",
- "cvv",
- "date",
- "date_interval",
- "dob",
- "driver_license",
- "email_address",
- "healthcare_number",
- "ip_address",
- "location",
- "name",
- "numerical_pii",
- "phone_number",
- "ssn",
- "url",
- "vehicle_id",
- "medical_code",
- "name_family",
- "name_given",
- "account_number",
- "event",
- "filename",
- "gender",
- "language",
- "location_address",
- "location_city",
- "location_coordinate",
- "location_country",
- "location_state",
- "location_zip",
- "marital_status",
- "money",
- "name_medical_professional",
- "occupation",
- "organization",
- "organization_medical_facility",
- "origin",
- "passport_number",
- "password",
- "physical_attribute",
- "political_affiliation",
- "religion",
- "time",
- "username",
- "zodiac_sign",
- "blood_type",
- "condition",
- "dose",
- "drug",
- "injury",
- "medical_process",
- "statistics",
- "routing_number",
- "corporate_action",
- "financial_metric",
- "product",
- "trend",
- "duration",
- "location_address_street",
- "all",
- "sexuality",
- "effect",
- "project",
- "organization_id",
- "day",
- "month",
- "year",
- ],
- typing.Any,
-]
diff --git a/skyvault/skyflow/generated/rest/files/types/deidentify_file_image_request_deidentify_image_entity_types_item.py b/skyvault/skyflow/generated/rest/files/types/deidentify_file_image_request_deidentify_image_entity_types_item.py
deleted file mode 100644
index 4597dc0f..00000000
--- a/skyvault/skyflow/generated/rest/files/types/deidentify_file_image_request_deidentify_image_entity_types_item.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-DeidentifyFileImageRequestDeidentifyImageEntityTypesItem = typing.Union[
- typing.Literal[
- "age",
- "bank_account",
- "credit_card",
- "credit_card_expiration",
- "cvv",
- "date",
- "date_interval",
- "dob",
- "driver_license",
- "email_address",
- "healthcare_number",
- "ip_address",
- "location",
- "name",
- "numerical_pii",
- "phone_number",
- "ssn",
- "url",
- "vehicle_id",
- "medical_code",
- "name_family",
- "name_given",
- "account_number",
- "event",
- "filename",
- "gender",
- "language",
- "location_address",
- "location_city",
- "location_coordinate",
- "location_country",
- "location_state",
- "location_zip",
- "marital_status",
- "money",
- "name_medical_professional",
- "occupation",
- "organization",
- "organization_medical_facility",
- "origin",
- "passport_number",
- "password",
- "physical_attribute",
- "political_affiliation",
- "religion",
- "time",
- "username",
- "zodiac_sign",
- "blood_type",
- "condition",
- "dose",
- "drug",
- "injury",
- "medical_process",
- "statistics",
- "routing_number",
- "corporate_action",
- "financial_metric",
- "product",
- "trend",
- "duration",
- "location_address_street",
- "all",
- "sexuality",
- "effect",
- "project",
- "organization_id",
- "day",
- "month",
- "year",
- ],
- typing.Any,
-]
diff --git a/skyvault/skyflow/generated/rest/files/types/deidentify_file_image_request_deidentify_image_masking_method.py b/skyvault/skyflow/generated/rest/files/types/deidentify_file_image_request_deidentify_image_masking_method.py
deleted file mode 100644
index c357821e..00000000
--- a/skyvault/skyflow/generated/rest/files/types/deidentify_file_image_request_deidentify_image_masking_method.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-DeidentifyFileImageRequestDeidentifyImageMaskingMethod = typing.Union[typing.Literal["blur", "blackbox"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/files/types/deidentify_file_request_deidentify_document_entity_types_item.py b/skyvault/skyflow/generated/rest/files/types/deidentify_file_request_deidentify_document_entity_types_item.py
deleted file mode 100644
index afcbe2ee..00000000
--- a/skyvault/skyflow/generated/rest/files/types/deidentify_file_request_deidentify_document_entity_types_item.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-DeidentifyFileRequestDeidentifyDocumentEntityTypesItem = typing.Union[
- typing.Literal[
- "age",
- "bank_account",
- "credit_card",
- "credit_card_expiration",
- "cvv",
- "date",
- "date_interval",
- "dob",
- "driver_license",
- "email_address",
- "healthcare_number",
- "ip_address",
- "location",
- "name",
- "numerical_pii",
- "phone_number",
- "ssn",
- "url",
- "vehicle_id",
- "medical_code",
- "name_family",
- "name_given",
- "account_number",
- "event",
- "filename",
- "gender",
- "language",
- "location_address",
- "location_city",
- "location_coordinate",
- "location_country",
- "location_state",
- "location_zip",
- "marital_status",
- "money",
- "name_medical_professional",
- "occupation",
- "organization",
- "organization_medical_facility",
- "origin",
- "passport_number",
- "password",
- "physical_attribute",
- "political_affiliation",
- "religion",
- "time",
- "username",
- "zodiac_sign",
- "blood_type",
- "condition",
- "dose",
- "drug",
- "injury",
- "medical_process",
- "statistics",
- "routing_number",
- "corporate_action",
- "financial_metric",
- "product",
- "trend",
- "duration",
- "location_address_street",
- "all",
- "sexuality",
- "effect",
- "project",
- "organization_id",
- "day",
- "month",
- "year",
- ],
- typing.Any,
-]
diff --git a/skyvault/skyflow/generated/rest/files/types/deidentify_file_request_deidentify_presentation_entity_types_item.py b/skyvault/skyflow/generated/rest/files/types/deidentify_file_request_deidentify_presentation_entity_types_item.py
deleted file mode 100644
index 69d40627..00000000
--- a/skyvault/skyflow/generated/rest/files/types/deidentify_file_request_deidentify_presentation_entity_types_item.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-DeidentifyFileRequestDeidentifyPresentationEntityTypesItem = typing.Union[
- typing.Literal[
- "age",
- "bank_account",
- "credit_card",
- "credit_card_expiration",
- "cvv",
- "date",
- "date_interval",
- "dob",
- "driver_license",
- "email_address",
- "healthcare_number",
- "ip_address",
- "location",
- "name",
- "numerical_pii",
- "phone_number",
- "ssn",
- "url",
- "vehicle_id",
- "medical_code",
- "name_family",
- "name_given",
- "account_number",
- "event",
- "filename",
- "gender",
- "language",
- "location_address",
- "location_city",
- "location_coordinate",
- "location_country",
- "location_state",
- "location_zip",
- "marital_status",
- "money",
- "name_medical_professional",
- "occupation",
- "organization",
- "organization_medical_facility",
- "origin",
- "passport_number",
- "password",
- "physical_attribute",
- "political_affiliation",
- "religion",
- "time",
- "username",
- "zodiac_sign",
- "blood_type",
- "condition",
- "dose",
- "drug",
- "injury",
- "medical_process",
- "statistics",
- "routing_number",
- "corporate_action",
- "financial_metric",
- "product",
- "trend",
- "duration",
- "location_address_street",
- "all",
- "sexuality",
- "effect",
- "project",
- "organization_id",
- "day",
- "month",
- "year",
- ],
- typing.Any,
-]
diff --git a/skyvault/skyflow/generated/rest/files/types/deidentify_file_request_deidentify_spreadsheet_entity_types_item.py b/skyvault/skyflow/generated/rest/files/types/deidentify_file_request_deidentify_spreadsheet_entity_types_item.py
deleted file mode 100644
index 0bb37078..00000000
--- a/skyvault/skyflow/generated/rest/files/types/deidentify_file_request_deidentify_spreadsheet_entity_types_item.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-DeidentifyFileRequestDeidentifySpreadsheetEntityTypesItem = typing.Union[
- typing.Literal[
- "age",
- "bank_account",
- "credit_card",
- "credit_card_expiration",
- "cvv",
- "date",
- "date_interval",
- "dob",
- "driver_license",
- "email_address",
- "healthcare_number",
- "ip_address",
- "location",
- "name",
- "numerical_pii",
- "phone_number",
- "ssn",
- "url",
- "vehicle_id",
- "medical_code",
- "name_family",
- "name_given",
- "account_number",
- "event",
- "filename",
- "gender",
- "language",
- "location_address",
- "location_city",
- "location_coordinate",
- "location_country",
- "location_state",
- "location_zip",
- "marital_status",
- "money",
- "name_medical_professional",
- "occupation",
- "organization",
- "organization_medical_facility",
- "origin",
- "passport_number",
- "password",
- "physical_attribute",
- "political_affiliation",
- "religion",
- "time",
- "username",
- "zodiac_sign",
- "blood_type",
- "condition",
- "dose",
- "drug",
- "injury",
- "medical_process",
- "statistics",
- "routing_number",
- "corporate_action",
- "financial_metric",
- "product",
- "trend",
- "duration",
- "location_address_street",
- "all",
- "sexuality",
- "effect",
- "project",
- "organization_id",
- "day",
- "month",
- "year",
- ],
- typing.Any,
-]
diff --git a/skyvault/skyflow/generated/rest/files/types/deidentify_file_request_deidentify_structured_text_entity_types_item.py b/skyvault/skyflow/generated/rest/files/types/deidentify_file_request_deidentify_structured_text_entity_types_item.py
deleted file mode 100644
index a487d969..00000000
--- a/skyvault/skyflow/generated/rest/files/types/deidentify_file_request_deidentify_structured_text_entity_types_item.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-DeidentifyFileRequestDeidentifyStructuredTextEntityTypesItem = typing.Union[
- typing.Literal[
- "age",
- "bank_account",
- "credit_card",
- "credit_card_expiration",
- "cvv",
- "date",
- "date_interval",
- "dob",
- "driver_license",
- "email_address",
- "healthcare_number",
- "ip_address",
- "location",
- "name",
- "numerical_pii",
- "phone_number",
- "ssn",
- "url",
- "vehicle_id",
- "medical_code",
- "name_family",
- "name_given",
- "account_number",
- "event",
- "filename",
- "gender",
- "language",
- "location_address",
- "location_city",
- "location_coordinate",
- "location_country",
- "location_state",
- "location_zip",
- "marital_status",
- "money",
- "name_medical_professional",
- "occupation",
- "organization",
- "organization_medical_facility",
- "origin",
- "passport_number",
- "password",
- "physical_attribute",
- "political_affiliation",
- "religion",
- "time",
- "username",
- "zodiac_sign",
- "blood_type",
- "condition",
- "dose",
- "drug",
- "injury",
- "medical_process",
- "statistics",
- "routing_number",
- "corporate_action",
- "financial_metric",
- "product",
- "trend",
- "duration",
- "location_address_street",
- "all",
- "sexuality",
- "effect",
- "project",
- "organization_id",
- "day",
- "month",
- "year",
- ],
- typing.Any,
-]
diff --git a/skyvault/skyflow/generated/rest/files/types/deidentify_file_request_deidentify_text_entity_types_item.py b/skyvault/skyflow/generated/rest/files/types/deidentify_file_request_deidentify_text_entity_types_item.py
deleted file mode 100644
index 2e6118cd..00000000
--- a/skyvault/skyflow/generated/rest/files/types/deidentify_file_request_deidentify_text_entity_types_item.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-DeidentifyFileRequestDeidentifyTextEntityTypesItem = typing.Union[
- typing.Literal[
- "age",
- "bank_account",
- "credit_card",
- "credit_card_expiration",
- "cvv",
- "date",
- "date_interval",
- "dob",
- "driver_license",
- "email_address",
- "healthcare_number",
- "ip_address",
- "location",
- "name",
- "numerical_pii",
- "phone_number",
- "ssn",
- "url",
- "vehicle_id",
- "medical_code",
- "name_family",
- "name_given",
- "account_number",
- "event",
- "filename",
- "gender",
- "language",
- "location_address",
- "location_city",
- "location_coordinate",
- "location_country",
- "location_state",
- "location_zip",
- "marital_status",
- "money",
- "name_medical_professional",
- "occupation",
- "organization",
- "organization_medical_facility",
- "origin",
- "passport_number",
- "password",
- "physical_attribute",
- "political_affiliation",
- "religion",
- "time",
- "username",
- "zodiac_sign",
- "blood_type",
- "condition",
- "dose",
- "drug",
- "injury",
- "medical_process",
- "statistics",
- "routing_number",
- "corporate_action",
- "financial_metric",
- "product",
- "trend",
- "duration",
- "location_address_street",
- "all",
- "sexuality",
- "effect",
- "project",
- "organization_id",
- "day",
- "month",
- "year",
- ],
- typing.Any,
-]
diff --git a/skyvault/skyflow/generated/rest/files/types/deidentify_file_request_entity_types_item.py b/skyvault/skyflow/generated/rest/files/types/deidentify_file_request_entity_types_item.py
deleted file mode 100644
index 6d7e8d38..00000000
--- a/skyvault/skyflow/generated/rest/files/types/deidentify_file_request_entity_types_item.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-DeidentifyFileRequestEntityTypesItem = typing.Union[
- typing.Literal[
- "age",
- "bank_account",
- "credit_card",
- "credit_card_expiration",
- "cvv",
- "date",
- "date_interval",
- "dob",
- "driver_license",
- "email_address",
- "healthcare_number",
- "ip_address",
- "location",
- "name",
- "numerical_pii",
- "phone_number",
- "ssn",
- "url",
- "vehicle_id",
- "medical_code",
- "name_family",
- "name_given",
- "account_number",
- "event",
- "filename",
- "gender",
- "language",
- "location_address",
- "location_city",
- "location_coordinate",
- "location_country",
- "location_state",
- "location_zip",
- "marital_status",
- "money",
- "name_medical_professional",
- "occupation",
- "organization",
- "organization_medical_facility",
- "origin",
- "passport_number",
- "password",
- "physical_attribute",
- "political_affiliation",
- "religion",
- "time",
- "username",
- "zodiac_sign",
- "blood_type",
- "condition",
- "dose",
- "drug",
- "injury",
- "medical_process",
- "statistics",
- "routing_number",
- "corporate_action",
- "financial_metric",
- "product",
- "trend",
- "duration",
- "location_address_street",
- "all",
- "sexuality",
- "effect",
- "project",
- "organization_id",
- "day",
- "month",
- "year",
- ],
- typing.Any,
-]
diff --git a/skyvault/skyflow/generated/rest/query/client.py b/skyvault/skyflow/generated/rest/query/client.py
index 28fd454e..2279b798 100644
--- a/skyvault/skyflow/generated/rest/query/client.py
+++ b/skyvault/skyflow/generated/rest/query/client.py
@@ -4,7 +4,7 @@
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.request_options import RequestOptions
-from ..types.v_1_get_query_response import V1GetQueryResponse
+from ..types.get_query_response import GetQueryResponse
from .raw_client import AsyncRawQueryClient, RawQueryClient
# this is used as the default value for optional parameters
@@ -26,13 +26,9 @@ def with_raw_response(self) -> RawQueryClient:
"""
return self._raw_client
- def query_service_execute_query(
- self,
- vault_id: str,
- *,
- query: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> V1GetQueryResponse:
+ def execute_query(
+ self, vault_id: str, *, query: str, request_options: typing.Optional[RequestOptions] = None
+ ) -> GetQueryResponse:
"""
Returns records for a valid SQL query. This endpoint - Can return redacted record values.
- Supports only the
SELECT command. - Returns a maximum of 25 records. To return additional records, perform another query using the
OFFSET keyword. - Can't modify the vault or perform transactions.
- Can't return tokens.
- Can't return file download or render URLs.
- Doesn't support the
WHERE keyword with columns using transient tokenization. - Doesn't support `?` conditional for columns with column-level encryption disabled.
@@ -41,7 +37,7 @@ def query_service_execute_query(
vault_id : str
ID of the vault.
- query : typing.Optional[str]
+ query : str
The SQL query to execute.
Supported commands: Supported operators: > < = AND OR NOT LIKE ILIKE NULL NOT NULL
Supported keywords: FROM JOIN INNER JOIN LEFT OUTER JOIN LEFT JOIN RIGHT OUTER JOIN RIGHT JOIN FULL OUTER JOIN FULL JOIN OFFSET LIMIT WHERE
Supported functions: AVG() SUM() COUNT() MIN() MAX() REDACTION()
request_options : typing.Optional[RequestOptions]
@@ -49,22 +45,22 @@ def query_service_execute_query(
Returns
-------
- V1GetQueryResponse
- A successful response.
+ GetQueryResponse
+ OK
Examples
--------
- from skyflow import Skyflow
+ from skyflow import SkyflowAuth
- client = Skyflow(
+ client = SkyflowAuth(
token="YOUR_TOKEN",
)
- client.query.query_service_execute_query(
+ client.query.execute_query(
vault_id="vaultID",
query='select * from opportunities where id="01010000ade21cded569d43944544ec6"',
)
"""
- _response = self._raw_client.query_service_execute_query(vault_id, query=query, request_options=request_options)
+ _response = self._raw_client.execute_query(vault_id, query=query, request_options=request_options)
return _response.data
@@ -83,13 +79,9 @@ def with_raw_response(self) -> AsyncRawQueryClient:
"""
return self._raw_client
- async def query_service_execute_query(
- self,
- vault_id: str,
- *,
- query: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> V1GetQueryResponse:
+ async def execute_query(
+ self, vault_id: str, *, query: str, request_options: typing.Optional[RequestOptions] = None
+ ) -> GetQueryResponse:
"""
Returns records for a valid SQL query. This endpoint - Can return redacted record values.
- Supports only the
SELECT command. - Returns a maximum of 25 records. To return additional records, perform another query using the
OFFSET keyword. - Can't modify the vault or perform transactions.
- Can't return tokens.
- Can't return file download or render URLs.
- Doesn't support the
WHERE keyword with columns using transient tokenization. - Doesn't support `?` conditional for columns with column-level encryption disabled.
@@ -98,7 +90,7 @@ async def query_service_execute_query(
vault_id : str
ID of the vault.
- query : typing.Optional[str]
+ query : str
The SQL query to execute.
Supported commands: Supported operators: > < = AND OR NOT LIKE ILIKE NULL NOT NULL
Supported keywords: FROM JOIN INNER JOIN LEFT OUTER JOIN LEFT JOIN RIGHT OUTER JOIN RIGHT JOIN FULL OUTER JOIN FULL JOIN OFFSET LIMIT WHERE
Supported functions: AVG() SUM() COUNT() MIN() MAX() REDACTION()
request_options : typing.Optional[RequestOptions]
@@ -106,22 +98,22 @@ async def query_service_execute_query(
Returns
-------
- V1GetQueryResponse
- A successful response.
+ GetQueryResponse
+ OK
Examples
--------
import asyncio
- from skyflow import AsyncSkyflow
+ from skyflow import AsyncSkyflowAuth
- client = AsyncSkyflow(
+ client = AsyncSkyflowAuth(
token="YOUR_TOKEN",
)
async def main() -> None:
- await client.query.query_service_execute_query(
+ await client.query.execute_query(
vault_id="vaultID",
query='select * from opportunities where id="01010000ade21cded569d43944544ec6"',
)
@@ -129,7 +121,5 @@ async def main() -> None:
asyncio.run(main())
"""
- _response = await self._raw_client.query_service_execute_query(
- vault_id, query=query, request_options=request_options
- )
+ _response = await self._raw_client.execute_query(vault_id, query=query, request_options=request_options)
return _response.data
diff --git a/skyvault/skyflow/generated/rest/query/raw_client.py b/skyvault/skyflow/generated/rest/query/raw_client.py
index 5450e1bf..6d8b33ad 100644
--- a/skyvault/skyflow/generated/rest/query/raw_client.py
+++ b/skyvault/skyflow/generated/rest/query/raw_client.py
@@ -6,11 +6,16 @@
from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.http_response import AsyncHttpResponse, HttpResponse
-from ..core.jsonable_encoder import jsonable_encoder
+from ..core.jsonable_encoder import encode_path_param
+from ..core.parse_error import ParsingError
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
-from ..errors.not_found_error import NotFoundError
-from ..types.v_1_get_query_response import V1GetQueryResponse
+from ..errors.bad_request_error import BadRequestError
+from ..errors.internal_server_error import InternalServerError
+from ..errors.unauthorized_error import UnauthorizedError
+from ..types.error_response import ErrorResponse
+from ..types.get_query_response import GetQueryResponse
+from pydantic import ValidationError
# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)
@@ -20,13 +25,9 @@ class RawQueryClient:
def __init__(self, *, client_wrapper: SyncClientWrapper):
self._client_wrapper = client_wrapper
- def query_service_execute_query(
- self,
- vault_id: str,
- *,
- query: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[V1GetQueryResponse]:
+ def execute_query(
+ self, vault_id: str, *, query: str, request_options: typing.Optional[RequestOptions] = None
+ ) -> HttpResponse[GetQueryResponse]:
"""
Returns records for a valid SQL query. This endpoint - Can return redacted record values.
- Supports only the
SELECT command. - Returns a maximum of 25 records. To return additional records, perform another query using the
OFFSET keyword. - Can't modify the vault or perform transactions.
- Can't return tokens.
- Can't return file download or render URLs.
- Doesn't support the
WHERE keyword with columns using transient tokenization. - Doesn't support `?` conditional for columns with column-level encryption disabled.
@@ -35,7 +36,7 @@ def query_service_execute_query(
vault_id : str
ID of the vault.
- query : typing.Optional[str]
+ query : str
The SQL query to execute.
Supported commands: Supported operators: > < = AND OR NOT LIKE ILIKE NULL NOT NULL
Supported keywords: FROM JOIN INNER JOIN LEFT OUTER JOIN LEFT JOIN RIGHT OUTER JOIN RIGHT JOIN FULL OUTER JOIN FULL JOIN OFFSET LIMIT WHERE
Supported functions: AVG() SUM() COUNT() MIN() MAX() REDACTION()
request_options : typing.Optional[RequestOptions]
@@ -43,11 +44,11 @@ def query_service_execute_query(
Returns
-------
- HttpResponse[V1GetQueryResponse]
- A successful response.
+ HttpResponse[GetQueryResponse]
+ OK
"""
_response = self._client_wrapper.httpx_client.request(
- f"v1/vaults/{jsonable_encoder(vault_id)}/query",
+ f"v1/vaults/{encode_path_param(vault_id)}/query",
method="POST",
json={
"query": query,
@@ -61,20 +62,42 @@ def query_service_execute_query(
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- V1GetQueryResponse,
+ GetQueryResponse,
parse_obj_as(
- type_=V1GetQueryResponse, # type: ignore
+ type_=GetQueryResponse, # type: ignore
object_=_response.json(),
),
)
return HttpResponse(response=_response, data=_data)
- if _response.status_code == 404:
- raise NotFoundError(
+ if _response.status_code == 400:
+ raise BadRequestError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 401:
+ raise UnauthorizedError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 500:
+ raise InternalServerError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -82,6 +105,10 @@ def query_service_execute_query(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
@@ -89,13 +116,9 @@ class AsyncRawQueryClient:
def __init__(self, *, client_wrapper: AsyncClientWrapper):
self._client_wrapper = client_wrapper
- async def query_service_execute_query(
- self,
- vault_id: str,
- *,
- query: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[V1GetQueryResponse]:
+ async def execute_query(
+ self, vault_id: str, *, query: str, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncHttpResponse[GetQueryResponse]:
"""
Returns records for a valid SQL query. This endpoint - Can return redacted record values.
- Supports only the
SELECT command. - Returns a maximum of 25 records. To return additional records, perform another query using the
OFFSET keyword. - Can't modify the vault or perform transactions.
- Can't return tokens.
- Can't return file download or render URLs.
- Doesn't support the
WHERE keyword with columns using transient tokenization. - Doesn't support `?` conditional for columns with column-level encryption disabled.
@@ -104,7 +127,7 @@ async def query_service_execute_query(
vault_id : str
ID of the vault.
- query : typing.Optional[str]
+ query : str
The SQL query to execute.
Supported commands: Supported operators: > < = AND OR NOT LIKE ILIKE NULL NOT NULL
Supported keywords: FROM JOIN INNER JOIN LEFT OUTER JOIN LEFT JOIN RIGHT OUTER JOIN RIGHT JOIN FULL OUTER JOIN FULL JOIN OFFSET LIMIT WHERE
Supported functions: AVG() SUM() COUNT() MIN() MAX() REDACTION()
request_options : typing.Optional[RequestOptions]
@@ -112,11 +135,11 @@ async def query_service_execute_query(
Returns
-------
- AsyncHttpResponse[V1GetQueryResponse]
- A successful response.
+ AsyncHttpResponse[GetQueryResponse]
+ OK
"""
_response = await self._client_wrapper.httpx_client.request(
- f"v1/vaults/{jsonable_encoder(vault_id)}/query",
+ f"v1/vaults/{encode_path_param(vault_id)}/query",
method="POST",
json={
"query": query,
@@ -130,20 +153,42 @@ async def query_service_execute_query(
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- V1GetQueryResponse,
+ GetQueryResponse,
parse_obj_as(
- type_=V1GetQueryResponse, # type: ignore
+ type_=GetQueryResponse, # type: ignore
object_=_response.json(),
),
)
return AsyncHttpResponse(response=_response, data=_data)
- if _response.status_code == 404:
- raise NotFoundError(
+ if _response.status_code == 400:
+ raise BadRequestError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 401:
+ raise UnauthorizedError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 500:
+ raise InternalServerError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -151,4 +196,8 @@ async def query_service_execute_query(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/skyvault/skyflow/generated/rest/raw_client.py b/skyvault/skyflow/generated/rest/raw_client.py
new file mode 100644
index 00000000..18893ef3
--- /dev/null
+++ b/skyvault/skyflow/generated/rest/raw_client.py
@@ -0,0 +1,86 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+from json.decoder import JSONDecodeError
+
+from .core.api_error import ApiError
+from .core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
+from .core.http_response import AsyncHttpResponse, HttpResponse
+from .core.jsonable_encoder import encode_path_param
+from .core.parse_error import ParsingError
+from .core.request_options import RequestOptions
+from pydantic import ValidationError
+
+
+class RawSkyflowAuth:
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ def patch_v2vaults_id(
+ self, vault_id: typing.Optional[str], *, request_options: typing.Optional[RequestOptions] = None
+ ) -> HttpResponse[None]:
+ """
+ Parameters
+ ----------
+ vault_id : typing.Optional[str]
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ HttpResponse[None]
+ """
+ _response = self._client_wrapper.httpx_client.request(
+ f"v2/vaults/{encode_path_param(vault_id)}",
+ method="PATCH",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ return HttpResponse(response=_response, data=None)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+
+
+class AsyncRawSkyflowAuth:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
+
+ async def patch_v2vaults_id(
+ self, vault_id: typing.Optional[str], *, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncHttpResponse[None]:
+ """
+ Parameters
+ ----------
+ vault_id : typing.Optional[str]
+
+ request_options : typing.Optional[RequestOptions]
+ Request-specific configuration.
+
+ Returns
+ -------
+ AsyncHttpResponse[None]
+ """
+ _response = await self._client_wrapper.httpx_client.request(
+ f"v2/vaults/{encode_path_param(vault_id)}",
+ method="PATCH",
+ request_options=request_options,
+ )
+ try:
+ if 200 <= _response.status_code < 300:
+ return AsyncHttpResponse(response=_response, data=None)
+ _response_json = _response.json()
+ except JSONDecodeError:
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/skyvault/skyflow/generated/rest/records/__init__.py b/skyvault/skyflow/generated/rest/records/__init__.py
index 19c344fa..2ba435aa 100644
--- a/skyvault/skyflow/generated/rest/records/__init__.py
+++ b/skyvault/skyflow/generated/rest/records/__init__.py
@@ -2,14 +2,51 @@
# isort: skip_file
-from .types import (
- RecordServiceBulkGetRecordRequestOrderBy,
- RecordServiceBulkGetRecordRequestRedaction,
- RecordServiceGetRecordRequestRedaction,
-)
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .types import (
+ GetRecordByIdRequestRedaction,
+ GetRecordsRequestOrderBy,
+ GetRecordsRequestRedaction,
+ InsertRecordRequestByot,
+ UpdateRecordRequestByot,
+ )
+_dynamic_imports: typing.Dict[str, str] = {
+ "GetRecordByIdRequestRedaction": ".types",
+ "GetRecordsRequestOrderBy": ".types",
+ "GetRecordsRequestRedaction": ".types",
+ "InsertRecordRequestByot": ".types",
+ "UpdateRecordRequestByot": ".types",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
__all__ = [
- "RecordServiceBulkGetRecordRequestOrderBy",
- "RecordServiceBulkGetRecordRequestRedaction",
- "RecordServiceGetRecordRequestRedaction",
+ "GetRecordByIdRequestRedaction",
+ "GetRecordsRequestOrderBy",
+ "GetRecordsRequestRedaction",
+ "InsertRecordRequestByot",
+ "UpdateRecordRequestByot",
]
diff --git a/skyvault/skyflow/generated/rest/records/client.py b/skyvault/skyflow/generated/rest/records/client.py
index 1b5ddeb7..67f2f870 100644
--- a/skyvault/skyflow/generated/rest/records/client.py
+++ b/skyvault/skyflow/generated/rest/records/client.py
@@ -2,25 +2,23 @@
import typing
-from .. import core
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.request_options import RequestOptions
-from ..types.upload_file_v_2_response import UploadFileV2Response
-from ..types.v_1_batch_operation_response import V1BatchOperationResponse
-from ..types.v_1_batch_record import V1BatchRecord
-from ..types.v_1_bulk_delete_record_response import V1BulkDeleteRecordResponse
-from ..types.v_1_bulk_get_record_response import V1BulkGetRecordResponse
-from ..types.v_1_byot import V1Byot
-from ..types.v_1_delete_file_response import V1DeleteFileResponse
-from ..types.v_1_delete_record_response import V1DeleteRecordResponse
-from ..types.v_1_field_records import V1FieldRecords
-from ..types.v_1_get_file_scan_status_response import V1GetFileScanStatusResponse
-from ..types.v_1_insert_record_response import V1InsertRecordResponse
-from ..types.v_1_update_record_response import V1UpdateRecordResponse
+from ..types.batch_operation_response import BatchOperationResponse
+from ..types.batch_record import BatchRecord
+from ..types.bulk_delete_record_response import BulkDeleteRecordResponse
+from ..types.bulk_get_record_response import BulkGetRecordResponse
+from ..types.delete_record_response import DeleteRecordResponse
+from ..types.field_records import FieldRecords
+from ..types.get_field_records import GetFieldRecords
+from ..types.insert_record_response import InsertRecordResponse
+from ..types.update_record_response import UpdateRecordResponse
from .raw_client import AsyncRawRecordsClient, RawRecordsClient
-from .types.record_service_bulk_get_record_request_order_by import RecordServiceBulkGetRecordRequestOrderBy
-from .types.record_service_bulk_get_record_request_redaction import RecordServiceBulkGetRecordRequestRedaction
-from .types.record_service_get_record_request_redaction import RecordServiceGetRecordRequestRedaction
+from .types.get_record_by_id_request_redaction import GetRecordByIdRequestRedaction
+from .types.get_records_request_order_by import GetRecordsRequestOrderBy
+from .types.get_records_request_redaction import GetRecordsRequestRedaction
+from .types.insert_record_request_byot import InsertRecordRequestByot
+from .types.update_record_request_byot import UpdateRecordRequestByot
# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)
@@ -41,15 +39,14 @@ def with_raw_response(self) -> RawRecordsClient:
"""
return self._raw_client
- def record_service_batch_operation(
+ def batch_operation(
self,
vault_id: str,
*,
- records: typing.Optional[typing.Sequence[V1BatchRecord]] = OMIT,
+ records: typing.Sequence[BatchRecord],
continue_on_error: typing.Optional[bool] = OMIT,
- byot: typing.Optional[V1Byot] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> V1BatchOperationResponse:
+ ) -> BatchOperationResponse:
"""
Performs multiple record operations in a single transaction.
@@ -58,33 +55,31 @@ def record_service_batch_operation(
vault_id : str
ID of the vault.
- records : typing.Optional[typing.Sequence[V1BatchRecord]]
+ records : typing.Sequence[BatchRecord]
Record operations to perform.
continue_on_error : typing.Optional[bool]
- Continue performing operations on partial errors.
-
- byot : typing.Optional[V1Byot]
+ If `true`, continues processing remaining operations when one operation returns an error. If `false`, stops processing remaining operations when one operation returns an error.
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- V1BatchOperationResponse
- A successful response.
+ BatchOperationResponse
+ OK
Examples
--------
- from skyflow import Skyflow, V1BatchRecord
+ from skyflow import BatchRecord, SkyflowAuth
- client = Skyflow(
+ client = SkyflowAuth(
token="YOUR_TOKEN",
)
- client.records.record_service_batch_operation(
+ client.records.batch_operation(
vault_id="vaultID",
records=[
- V1BatchRecord(
+ BatchRecord(
fields={
"drivers_license_number": "89867453",
"name": "Connor",
@@ -99,7 +94,8 @@ def record_service_batch_operation(
download_url=False,
upsert="drivers_license_number",
),
- V1BatchRecord(
+ BatchRecord(
+ fields={"key": "value"},
table_name="persons",
method="GET",
batch_id="persons-12345",
@@ -111,18 +107,18 @@ def record_service_batch_operation(
],
)
"""
- _response = self._raw_client.record_service_batch_operation(
- vault_id, records=records, continue_on_error=continue_on_error, byot=byot, request_options=request_options
+ _response = self._raw_client.batch_operation(
+ vault_id, records=records, continue_on_error=continue_on_error, request_options=request_options
)
return _response.data
- def record_service_bulk_get_record(
+ def get_records(
self,
vault_id: str,
object_name: str,
*,
skyflow_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
- redaction: typing.Optional[RecordServiceBulkGetRecordRequestRedaction] = None,
+ redaction: typing.Optional[GetRecordsRequestRedaction] = None,
tokenization: typing.Optional[bool] = None,
fields: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
offset: typing.Optional[str] = None,
@@ -130,78 +126,62 @@ def record_service_bulk_get_record(
download_url: typing.Optional[bool] = None,
column_name: typing.Optional[str] = None,
column_values: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
- order_by: typing.Optional[RecordServiceBulkGetRecordRequestOrderBy] = None,
+ order_by: typing.Optional[GetRecordsRequestOrderBy] = None,
+ return_file_metadata: typing.Optional[bool] = None,
request_options: typing.Optional[RequestOptions] = None,
- ) -> V1BulkGetRecordResponse:
+ ) -> BulkGetRecordResponse:
"""
- Gets the specified records from a table.
+ Returns the specified records from a table.
Parameters
----------
vault_id : str
- ID of the vault.
object_name : str
- Name of the table that contains the records.
skyflow_ids : typing.Optional[typing.Union[str, typing.Sequence[str]]]
- `skyflow_id` values of the records to return, with one value per `skyflow_ids` URL parameter. For example, `?skyflow_ids=abc&skyflow_ids=123`.
If not specified, returns the first 25 records in the table.
- redaction : typing.Optional[RecordServiceBulkGetRecordRequestRedaction]
- Redaction level to enforce for the returned records. Subject to policies assigned to the API caller.
+ redaction : typing.Optional[GetRecordsRequestRedaction]
tokenization : typing.Optional[bool]
- If `true`, this operation returns tokens for fields with tokenization enabled. Only applicable if `skyflow_id` values are specified.
fields : typing.Optional[typing.Union[str, typing.Sequence[str]]]
- Fields to return for the record, with one value per `fields` URL parameter. For example, `?fields=abc&fields=123`.
If not specified, returns all fields.
offset : typing.Optional[str]
- Record position at which to start receiving data.
limit : typing.Optional[str]
- Number of record to return. Maximum 25.
download_url : typing.Optional[bool]
- If `true`, returns download URLs for fields with a file data type. URLs are valid for 15 minutes. If virus scanning is enabled, only returns if the file is clean.
column_name : typing.Optional[str]
- Name of the column. It must be configured as unique in the schema. If you provide both column name or column value, you cannot use `skyflow_ids`. Passing either of these parameters with `skyflow_ids` returns an error.
column_values : typing.Optional[typing.Union[str, typing.Sequence[str]]]
- Column values of the records to return, with one value per `column_values` URL parameter. For example, `?column_values=abc&column_values=123`.
`column_name` is mandatory when providing `column_values`. If you use column name or column value, you cannot use `skyflow_ids`. Passing either of these parameters with `skyflow_ids` returns an error.
- order_by : typing.Optional[RecordServiceBulkGetRecordRequestOrderBy]
- Order to return records, based on `skyflow_id` values. To disable, set to `NONE`.
+ order_by : typing.Optional[GetRecordsRequestOrderBy]
+
+ return_file_metadata : typing.Optional[bool]
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- V1BulkGetRecordResponse
- A successful response.
+ BulkGetRecordResponse
+ OK
Examples
--------
- from skyflow import Skyflow
+ from skyflow import SkyflowAuth
- client = Skyflow(
+ client = SkyflowAuth(
token="YOUR_TOKEN",
)
- client.records.record_service_bulk_get_record(
+ client.records.get_records(
vault_id="vaultID",
object_name="objectName",
- redaction="DEFAULT",
- tokenization=True,
- offset="offset",
- limit="limit",
- download_url=True,
- column_name="column_name",
- order_by="ASCENDING",
)
"""
- _response = self._raw_client.record_service_bulk_get_record(
+ _response = self._raw_client.get_records(
vault_id,
object_name,
skyflow_ids=skyflow_ids,
@@ -214,34 +194,33 @@ def record_service_bulk_get_record(
column_name=column_name,
column_values=column_values,
order_by=order_by,
+ return_file_metadata=return_file_metadata,
request_options=request_options,
)
return _response.data
- def record_service_insert_record(
+ def insert_records(
self,
vault_id: str,
object_name: str,
*,
- records: typing.Optional[typing.Sequence[V1FieldRecords]] = OMIT,
+ records: typing.Sequence[FieldRecords],
tokenization: typing.Optional[bool] = OMIT,
upsert: typing.Optional[str] = OMIT,
homogeneous: typing.Optional[bool] = OMIT,
- byot: typing.Optional[V1Byot] = OMIT,
+ byot: typing.Optional[InsertRecordRequestByot] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> V1InsertRecordResponse:
+ ) -> InsertRecordResponse:
"""
Inserts a record in the specified table.
The time-to-live (TTL) for a transient field begins when the field value is set during record insertion.
Columns that have a string data type and a uniqueness constraint accept strings up to 2500 characters. If an inserted string exceeds 2500 characters, the call returns a token insertion error.
Parameters
----------
vault_id : str
- ID of the vault.
object_name : str
- Name of the table.
- records : typing.Optional[typing.Sequence[V1FieldRecords]]
+ records : typing.Sequence[FieldRecords]
Record values and tokens.
tokenization : typing.Optional[bool]
@@ -253,28 +232,29 @@ def record_service_insert_record(
homogeneous : typing.Optional[bool]
If `true`, this operation mandates that all the records have the same fields. This parameter does not work with upsert.
- byot : typing.Optional[V1Byot]
+ byot : typing.Optional[InsertRecordRequestByot]
+ Token insertion behavior.
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- V1InsertRecordResponse
- A successful response.
+ InsertRecordResponse
+ OK
Examples
--------
- from skyflow import Skyflow, V1FieldRecords
+ from skyflow import FieldRecords, SkyflowAuth
- client = Skyflow(
+ client = SkyflowAuth(
token="YOUR_TOKEN",
)
- client.records.record_service_insert_record(
+ client.records.insert_records(
vault_id="vaultID",
object_name="objectName",
records=[
- V1FieldRecords(
+ FieldRecords(
fields={
"drivers_license_number": "13456789",
"name": "John",
@@ -282,7 +262,7 @@ def record_service_insert_record(
"ssn": "123-45-6789",
},
),
- V1FieldRecords(
+ FieldRecords(
fields={
"drivers_license_number": "98765432",
"name": "James",
@@ -296,7 +276,7 @@ def record_service_insert_record(
homogeneous=False,
)
"""
- _response = self._raw_client.record_service_insert_record(
+ _response = self._raw_client.insert_records(
vault_id,
object_name,
records=records,
@@ -308,14 +288,14 @@ def record_service_insert_record(
)
return _response.data
- def record_service_bulk_delete_record(
+ def delete_records(
self,
vault_id: str,
object_name: str,
*,
skyflow_ids: typing.Optional[typing.Sequence[str]] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> V1BulkDeleteRecordResponse:
+ ) -> BulkDeleteRecordResponse:
"""
Deletes the specified records from a table.
@@ -335,17 +315,17 @@ def record_service_bulk_delete_record(
Returns
-------
- V1BulkDeleteRecordResponse
- A successful response.
+ BulkDeleteRecordResponse
+ OK
Examples
--------
- from skyflow import Skyflow
+ from skyflow import SkyflowAuth
- client = Skyflow(
+ client = SkyflowAuth(
token="YOUR_TOKEN",
)
- client.records.record_service_bulk_delete_record(
+ client.records.delete_records(
vault_id="vaultID",
object_name="objectName",
skyflow_ids=[
@@ -354,74 +334,67 @@ def record_service_bulk_delete_record(
],
)
"""
- _response = self._raw_client.record_service_bulk_delete_record(
+ _response = self._raw_client.delete_records(
vault_id, object_name, skyflow_ids=skyflow_ids, request_options=request_options
)
return _response.data
- def record_service_get_record(
+ def get_record_by_id(
self,
vault_id: str,
object_name: str,
id: str,
*,
- redaction: typing.Optional[RecordServiceGetRecordRequestRedaction] = None,
+ redaction: typing.Optional[GetRecordByIdRequestRedaction] = None,
tokenization: typing.Optional[bool] = None,
fields: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
download_url: typing.Optional[bool] = None,
+ return_file_metadata: typing.Optional[bool] = None,
request_options: typing.Optional[RequestOptions] = None,
- ) -> V1FieldRecords:
+ ) -> GetFieldRecords:
"""
Returns the specified record from a table.
Parameters
----------
vault_id : str
- ID of the vault.
object_name : str
- Name of the table.
id : str
- `skyflow_id` of the record.
- redaction : typing.Optional[RecordServiceGetRecordRequestRedaction]
- Redaction level to enforce for the returned record. Subject to policies assigned to the API caller.
+ redaction : typing.Optional[GetRecordByIdRequestRedaction]
tokenization : typing.Optional[bool]
- If `true`, this operation returns tokens for fields with tokenization enabled. Only applicable if `skyflow_id` values are specified.
fields : typing.Optional[typing.Union[str, typing.Sequence[str]]]
- Fields to return for the record, with one value per `fields` URL parameter. For example, `?fields=abc&fields=123`.
If not specified, returns all fields.
download_url : typing.Optional[bool]
- If `true`, returns download URLs for fields with a file data type. URLs are valid for 15 minutes. If virus scanning is enabled, only returns if the file is clean.
+
+ return_file_metadata : typing.Optional[bool]
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- V1FieldRecords
- A successful response.
+ GetFieldRecords
+ OK
Examples
--------
- from skyflow import Skyflow
+ from skyflow import SkyflowAuth
- client = Skyflow(
+ client = SkyflowAuth(
token="YOUR_TOKEN",
)
- client.records.record_service_get_record(
+ client.records.get_record_by_id(
vault_id="vaultID",
object_name="objectName",
id="ID",
- redaction="DEFAULT",
- tokenization=True,
- download_url=True,
)
"""
- _response = self._raw_client.record_service_get_record(
+ _response = self._raw_client.get_record_by_id(
vault_id,
object_name,
id,
@@ -429,62 +402,61 @@ def record_service_get_record(
tokenization=tokenization,
fields=fields,
download_url=download_url,
+ return_file_metadata=return_file_metadata,
request_options=request_options,
)
return _response.data
- def record_service_update_record(
+ def update_record(
self,
vault_id: str,
object_name: str,
id: str,
*,
- record: typing.Optional[V1FieldRecords] = OMIT,
+ record: typing.Optional[FieldRecords] = OMIT,
tokenization: typing.Optional[bool] = OMIT,
- byot: typing.Optional[V1Byot] = OMIT,
+ byot: typing.Optional[UpdateRecordRequestByot] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> V1UpdateRecordResponse:
+ ) -> UpdateRecordResponse:
"""
Updates the specified record in a table.
When you update a field, include the entire contents you want the field to store. For JSON fields, include all nested fields and values. If a nested field isn't included, it's removed.
The time-to-live (TTL) for a transient field resets when the field value is updated.
Parameters
----------
vault_id : str
- ID of the vault.
object_name : str
- Name of the table.
id : str
- `skyflow_id` of the record.
- record : typing.Optional[V1FieldRecords]
+ record : typing.Optional[FieldRecords]
tokenization : typing.Optional[bool]
If `true`, this operation returns tokens for fields with tokenization enabled.
- byot : typing.Optional[V1Byot]
+ byot : typing.Optional[UpdateRecordRequestByot]
+ Token insertion behavior.
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- V1UpdateRecordResponse
- A successful response.
+ UpdateRecordResponse
+ OK
Examples
--------
- from skyflow import Skyflow, V1FieldRecords
+ from skyflow import FieldRecords, SkyflowAuth
- client = Skyflow(
+ client = SkyflowAuth(
token="YOUR_TOKEN",
)
- client.records.record_service_update_record(
+ client.records.update_record(
vault_id="vaultID",
object_name="objectName",
id="ID",
- record=V1FieldRecords(
+ record=FieldRecords(
fields={
"drivers_license_number": "89867453",
"name": "Steve Smith",
@@ -495,7 +467,7 @@ def record_service_update_record(
tokenization=True,
)
"""
- _response = self._raw_client.record_service_update_record(
+ _response = self._raw_client.update_record(
vault_id,
object_name,
id,
@@ -506,9 +478,9 @@ def record_service_update_record(
)
return _response.data
- def record_service_delete_record(
+ def delete_record(
self, vault_id: str, object_name: str, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> V1DeleteRecordResponse:
+ ) -> DeleteRecordResponse:
"""
Deletes the specified record from a table.
Note: This method doesn't delete transient field tokens. Transient field values are available until they expire based on the fields' time-to-live (TTL) setting.
@@ -528,253 +500,23 @@ def record_service_delete_record(
Returns
-------
- V1DeleteRecordResponse
- A successful response.
-
- Examples
- --------
- from skyflow import Skyflow
-
- client = Skyflow(
- token="YOUR_TOKEN",
- )
- client.records.record_service_delete_record(
- vault_id="vaultID",
- object_name="objectName",
- id="ID",
- )
- """
- _response = self._raw_client.record_service_delete_record(
- vault_id, object_name, id, request_options=request_options
- )
- return _response.data
-
- def file_service_upload_file(
- self,
- vault_id: str,
- object_name: str,
- id: str,
- *,
- file: typing.Optional[core.File] = OMIT,
- column_name: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> V1UpdateRecordResponse:
- """
- Uploads a file to the specified record.
-
- Parameters
- ----------
- vault_id : str
- ID of the vault.
-
- object_name : str
- Name of the table.
-
- id : str
- `skyflow_id` of the record.
-
- file : typing.Optional[core.File]
- See core.File for more documentation
-
- column_name : typing.Optional[str]
- Name of the column to store the file in. The column must have a file data type.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- V1UpdateRecordResponse
- A successful response.
+ DeleteRecordResponse
+ OK
Examples
--------
- from skyflow import Skyflow
+ from skyflow import SkyflowAuth
- client = Skyflow(
+ client = SkyflowAuth(
token="YOUR_TOKEN",
)
- client.records.file_service_upload_file(
+ client.records.delete_record(
vault_id="vaultID",
object_name="objectName",
id="ID",
)
"""
- _response = self._raw_client.file_service_upload_file(
- vault_id, object_name, id, file=file, column_name=column_name, request_options=request_options
- )
- return _response.data
-
- def file_service_delete_file(
- self,
- vault_id: str,
- table_name: str,
- id: str,
- column_name: str,
- *,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> V1DeleteFileResponse:
- """
- Deletes a file from the specified record.
-
- Parameters
- ----------
- vault_id : str
- ID of the vault.
-
- table_name : str
- Name of the table.
-
- id : str
- `skyflow_id` of the record.
-
- column_name : str
- Name of the column that contains the file.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- V1DeleteFileResponse
- A successful response.
-
- Examples
- --------
- from skyflow import Skyflow
-
- client = Skyflow(
- token="YOUR_TOKEN",
- )
- client.records.file_service_delete_file(
- vault_id="vaultID",
- table_name="tableName",
- id="ID",
- column_name="columnName",
- )
- """
- _response = self._raw_client.file_service_delete_file(
- vault_id, table_name, id, column_name, request_options=request_options
- )
- return _response.data
-
- def file_service_get_file_scan_status(
- self,
- vault_id: str,
- table_name: str,
- id: str,
- column_name: str,
- *,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> V1GetFileScanStatusResponse:
- """
- Returns the anti-virus scan status of a file.
-
- Parameters
- ----------
- vault_id : str
- ID of the vault.
-
- table_name : str
- Name of the table.
-
- id : str
- `skyflow_id` of the record.
-
- column_name : str
- Name of the column that contains the file.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- V1GetFileScanStatusResponse
- A successful response.
-
- Examples
- --------
- from skyflow import Skyflow
-
- client = Skyflow(
- token="YOUR_TOKEN",
- )
- client.records.file_service_get_file_scan_status(
- vault_id="vaultID",
- table_name="tableName",
- id="ID",
- column_name="columnName",
- )
- """
- _response = self._raw_client.file_service_get_file_scan_status(
- vault_id, table_name, id, column_name, request_options=request_options
- )
- return _response.data
-
- def upload_file_v_2(
- self,
- vault_id: str,
- *,
- table_name: str,
- column_name: str,
- file: core.File,
- skyflow_id: typing.Optional[str] = OMIT,
- return_file_metadata: typing.Optional[bool] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> UploadFileV2Response:
- """
- Uploads the specified file to a record. If an existing record isn't specified, creates a new record and uploads the file to that record.
-
- Parameters
- ----------
- vault_id : str
- ID of the vault.
-
- table_name : str
- Name of the table to upload the file to.
-
- column_name : str
- Name of the column to upload the file to. The column must have a `file` data type.
-
- file : core.File
- See core.File for more documentation
-
- skyflow_id : typing.Optional[str]
- Skyflow ID of the record to upload the file to. If `skyflowID` isn't specified, a new record will be created.
-
- return_file_metadata : typing.Optional[bool]
- If `true`, returns metadata about the uploaded file.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- UploadFileV2Response
- File uploaded successfully.
-
- Examples
- --------
- from skyflow import Skyflow
-
- client = Skyflow(
- token="YOUR_TOKEN",
- )
- client.records.upload_file_v_2(
- vault_id="d4410ea01d83473ca09a24c6b03096d4",
- table_name="tableName",
- column_name="columnName",
- )
- """
- _response = self._raw_client.upload_file_v_2(
- vault_id,
- table_name=table_name,
- column_name=column_name,
- file=file,
- skyflow_id=skyflow_id,
- return_file_metadata=return_file_metadata,
- request_options=request_options,
- )
+ _response = self._raw_client.delete_record(vault_id, object_name, id, request_options=request_options)
return _response.data
@@ -793,15 +535,14 @@ def with_raw_response(self) -> AsyncRawRecordsClient:
"""
return self._raw_client
- async def record_service_batch_operation(
+ async def batch_operation(
self,
vault_id: str,
*,
- records: typing.Optional[typing.Sequence[V1BatchRecord]] = OMIT,
+ records: typing.Sequence[BatchRecord],
continue_on_error: typing.Optional[bool] = OMIT,
- byot: typing.Optional[V1Byot] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> V1BatchOperationResponse:
+ ) -> BatchOperationResponse:
"""
Performs multiple record operations in a single transaction.
@@ -810,38 +551,36 @@ async def record_service_batch_operation(
vault_id : str
ID of the vault.
- records : typing.Optional[typing.Sequence[V1BatchRecord]]
+ records : typing.Sequence[BatchRecord]
Record operations to perform.
continue_on_error : typing.Optional[bool]
- Continue performing operations on partial errors.
-
- byot : typing.Optional[V1Byot]
+ If `true`, continues processing remaining operations when one operation returns an error. If `false`, stops processing remaining operations when one operation returns an error.
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- V1BatchOperationResponse
- A successful response.
+ BatchOperationResponse
+ OK
Examples
--------
import asyncio
- from skyflow import AsyncSkyflow, V1BatchRecord
+ from skyflow import AsyncSkyflowAuth, BatchRecord
- client = AsyncSkyflow(
+ client = AsyncSkyflowAuth(
token="YOUR_TOKEN",
)
async def main() -> None:
- await client.records.record_service_batch_operation(
+ await client.records.batch_operation(
vault_id="vaultID",
records=[
- V1BatchRecord(
+ BatchRecord(
fields={
"drivers_license_number": "89867453",
"name": "Connor",
@@ -856,7 +595,8 @@ async def main() -> None:
download_url=False,
upsert="drivers_license_number",
),
- V1BatchRecord(
+ BatchRecord(
+ fields={"key": "value"},
table_name="persons",
method="GET",
batch_id="persons-12345",
@@ -871,18 +611,18 @@ async def main() -> None:
asyncio.run(main())
"""
- _response = await self._raw_client.record_service_batch_operation(
- vault_id, records=records, continue_on_error=continue_on_error, byot=byot, request_options=request_options
+ _response = await self._raw_client.batch_operation(
+ vault_id, records=records, continue_on_error=continue_on_error, request_options=request_options
)
return _response.data
- async def record_service_bulk_get_record(
+ async def get_records(
self,
vault_id: str,
object_name: str,
*,
skyflow_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
- redaction: typing.Optional[RecordServiceBulkGetRecordRequestRedaction] = None,
+ redaction: typing.Optional[GetRecordsRequestRedaction] = None,
tokenization: typing.Optional[bool] = None,
fields: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
offset: typing.Optional[str] = None,
@@ -890,86 +630,70 @@ async def record_service_bulk_get_record(
download_url: typing.Optional[bool] = None,
column_name: typing.Optional[str] = None,
column_values: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
- order_by: typing.Optional[RecordServiceBulkGetRecordRequestOrderBy] = None,
+ order_by: typing.Optional[GetRecordsRequestOrderBy] = None,
+ return_file_metadata: typing.Optional[bool] = None,
request_options: typing.Optional[RequestOptions] = None,
- ) -> V1BulkGetRecordResponse:
+ ) -> BulkGetRecordResponse:
"""
- Gets the specified records from a table.
+ Returns the specified records from a table.
Parameters
----------
vault_id : str
- ID of the vault.
object_name : str
- Name of the table that contains the records.
skyflow_ids : typing.Optional[typing.Union[str, typing.Sequence[str]]]
- `skyflow_id` values of the records to return, with one value per `skyflow_ids` URL parameter. For example, `?skyflow_ids=abc&skyflow_ids=123`.
If not specified, returns the first 25 records in the table.
- redaction : typing.Optional[RecordServiceBulkGetRecordRequestRedaction]
- Redaction level to enforce for the returned records. Subject to policies assigned to the API caller.
+ redaction : typing.Optional[GetRecordsRequestRedaction]
tokenization : typing.Optional[bool]
- If `true`, this operation returns tokens for fields with tokenization enabled. Only applicable if `skyflow_id` values are specified.
fields : typing.Optional[typing.Union[str, typing.Sequence[str]]]
- Fields to return for the record, with one value per `fields` URL parameter. For example, `?fields=abc&fields=123`.
If not specified, returns all fields.
offset : typing.Optional[str]
- Record position at which to start receiving data.
limit : typing.Optional[str]
- Number of record to return. Maximum 25.
download_url : typing.Optional[bool]
- If `true`, returns download URLs for fields with a file data type. URLs are valid for 15 minutes. If virus scanning is enabled, only returns if the file is clean.
column_name : typing.Optional[str]
- Name of the column. It must be configured as unique in the schema. If you provide both column name or column value, you cannot use `skyflow_ids`. Passing either of these parameters with `skyflow_ids` returns an error.
column_values : typing.Optional[typing.Union[str, typing.Sequence[str]]]
- Column values of the records to return, with one value per `column_values` URL parameter. For example, `?column_values=abc&column_values=123`.
`column_name` is mandatory when providing `column_values`. If you use column name or column value, you cannot use `skyflow_ids`. Passing either of these parameters with `skyflow_ids` returns an error.
- order_by : typing.Optional[RecordServiceBulkGetRecordRequestOrderBy]
- Order to return records, based on `skyflow_id` values. To disable, set to `NONE`.
+ order_by : typing.Optional[GetRecordsRequestOrderBy]
+
+ return_file_metadata : typing.Optional[bool]
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- V1BulkGetRecordResponse
- A successful response.
+ BulkGetRecordResponse
+ OK
Examples
--------
import asyncio
- from skyflow import AsyncSkyflow
+ from skyflow import AsyncSkyflowAuth
- client = AsyncSkyflow(
+ client = AsyncSkyflowAuth(
token="YOUR_TOKEN",
)
async def main() -> None:
- await client.records.record_service_bulk_get_record(
+ await client.records.get_records(
vault_id="vaultID",
object_name="objectName",
- redaction="DEFAULT",
- tokenization=True,
- offset="offset",
- limit="limit",
- download_url=True,
- column_name="column_name",
- order_by="ASCENDING",
)
asyncio.run(main())
"""
- _response = await self._raw_client.record_service_bulk_get_record(
+ _response = await self._raw_client.get_records(
vault_id,
object_name,
skyflow_ids=skyflow_ids,
@@ -982,34 +706,33 @@ async def main() -> None:
column_name=column_name,
column_values=column_values,
order_by=order_by,
+ return_file_metadata=return_file_metadata,
request_options=request_options,
)
return _response.data
- async def record_service_insert_record(
+ async def insert_records(
self,
vault_id: str,
object_name: str,
*,
- records: typing.Optional[typing.Sequence[V1FieldRecords]] = OMIT,
+ records: typing.Sequence[FieldRecords],
tokenization: typing.Optional[bool] = OMIT,
upsert: typing.Optional[str] = OMIT,
homogeneous: typing.Optional[bool] = OMIT,
- byot: typing.Optional[V1Byot] = OMIT,
+ byot: typing.Optional[InsertRecordRequestByot] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> V1InsertRecordResponse:
+ ) -> InsertRecordResponse:
"""
Inserts a record in the specified table.
The time-to-live (TTL) for a transient field begins when the field value is set during record insertion.
Columns that have a string data type and a uniqueness constraint accept strings up to 2500 characters. If an inserted string exceeds 2500 characters, the call returns a token insertion error.
Parameters
----------
vault_id : str
- ID of the vault.
object_name : str
- Name of the table.
- records : typing.Optional[typing.Sequence[V1FieldRecords]]
+ records : typing.Sequence[FieldRecords]
Record values and tokens.
tokenization : typing.Optional[bool]
@@ -1021,33 +744,34 @@ async def record_service_insert_record(
homogeneous : typing.Optional[bool]
If `true`, this operation mandates that all the records have the same fields. This parameter does not work with upsert.
- byot : typing.Optional[V1Byot]
+ byot : typing.Optional[InsertRecordRequestByot]
+ Token insertion behavior.
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- V1InsertRecordResponse
- A successful response.
+ InsertRecordResponse
+ OK
Examples
--------
import asyncio
- from skyflow import AsyncSkyflow, V1FieldRecords
+ from skyflow import AsyncSkyflowAuth, FieldRecords
- client = AsyncSkyflow(
+ client = AsyncSkyflowAuth(
token="YOUR_TOKEN",
)
async def main() -> None:
- await client.records.record_service_insert_record(
+ await client.records.insert_records(
vault_id="vaultID",
object_name="objectName",
records=[
- V1FieldRecords(
+ FieldRecords(
fields={
"drivers_license_number": "13456789",
"name": "John",
@@ -1055,7 +779,7 @@ async def main() -> None:
"ssn": "123-45-6789",
},
),
- V1FieldRecords(
+ FieldRecords(
fields={
"drivers_license_number": "98765432",
"name": "James",
@@ -1072,7 +796,7 @@ async def main() -> None:
asyncio.run(main())
"""
- _response = await self._raw_client.record_service_insert_record(
+ _response = await self._raw_client.insert_records(
vault_id,
object_name,
records=records,
@@ -1084,14 +808,14 @@ async def main() -> None:
)
return _response.data
- async def record_service_bulk_delete_record(
+ async def delete_records(
self,
vault_id: str,
object_name: str,
*,
skyflow_ids: typing.Optional[typing.Sequence[str]] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> V1BulkDeleteRecordResponse:
+ ) -> BulkDeleteRecordResponse:
"""
Deletes the specified records from a table.
@@ -1111,22 +835,22 @@ async def record_service_bulk_delete_record(
Returns
-------
- V1BulkDeleteRecordResponse
- A successful response.
+ BulkDeleteRecordResponse
+ OK
Examples
--------
import asyncio
- from skyflow import AsyncSkyflow
+ from skyflow import AsyncSkyflowAuth
- client = AsyncSkyflow(
+ client = AsyncSkyflowAuth(
token="YOUR_TOKEN",
)
async def main() -> None:
- await client.records.record_service_bulk_delete_record(
+ await client.records.delete_records(
vault_id="vaultID",
object_name="objectName",
skyflow_ids=[
@@ -1138,82 +862,75 @@ async def main() -> None:
asyncio.run(main())
"""
- _response = await self._raw_client.record_service_bulk_delete_record(
+ _response = await self._raw_client.delete_records(
vault_id, object_name, skyflow_ids=skyflow_ids, request_options=request_options
)
return _response.data
- async def record_service_get_record(
+ async def get_record_by_id(
self,
vault_id: str,
object_name: str,
id: str,
*,
- redaction: typing.Optional[RecordServiceGetRecordRequestRedaction] = None,
+ redaction: typing.Optional[GetRecordByIdRequestRedaction] = None,
tokenization: typing.Optional[bool] = None,
fields: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
download_url: typing.Optional[bool] = None,
+ return_file_metadata: typing.Optional[bool] = None,
request_options: typing.Optional[RequestOptions] = None,
- ) -> V1FieldRecords:
+ ) -> GetFieldRecords:
"""
Returns the specified record from a table.
Parameters
----------
vault_id : str
- ID of the vault.
object_name : str
- Name of the table.
id : str
- `skyflow_id` of the record.
- redaction : typing.Optional[RecordServiceGetRecordRequestRedaction]
- Redaction level to enforce for the returned record. Subject to policies assigned to the API caller.
+ redaction : typing.Optional[GetRecordByIdRequestRedaction]
tokenization : typing.Optional[bool]
- If `true`, this operation returns tokens for fields with tokenization enabled. Only applicable if `skyflow_id` values are specified.
fields : typing.Optional[typing.Union[str, typing.Sequence[str]]]
- Fields to return for the record, with one value per `fields` URL parameter. For example, `?fields=abc&fields=123`.
If not specified, returns all fields.
download_url : typing.Optional[bool]
- If `true`, returns download URLs for fields with a file data type. URLs are valid for 15 minutes. If virus scanning is enabled, only returns if the file is clean.
+
+ return_file_metadata : typing.Optional[bool]
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- V1FieldRecords
- A successful response.
+ GetFieldRecords
+ OK
Examples
--------
import asyncio
- from skyflow import AsyncSkyflow
+ from skyflow import AsyncSkyflowAuth
- client = AsyncSkyflow(
+ client = AsyncSkyflowAuth(
token="YOUR_TOKEN",
)
async def main() -> None:
- await client.records.record_service_get_record(
+ await client.records.get_record_by_id(
vault_id="vaultID",
object_name="objectName",
id="ID",
- redaction="DEFAULT",
- tokenization=True,
- download_url=True,
)
asyncio.run(main())
"""
- _response = await self._raw_client.record_service_get_record(
+ _response = await self._raw_client.get_record_by_id(
vault_id,
object_name,
id,
@@ -1221,67 +938,66 @@ async def main() -> None:
tokenization=tokenization,
fields=fields,
download_url=download_url,
+ return_file_metadata=return_file_metadata,
request_options=request_options,
)
return _response.data
- async def record_service_update_record(
+ async def update_record(
self,
vault_id: str,
object_name: str,
id: str,
*,
- record: typing.Optional[V1FieldRecords] = OMIT,
+ record: typing.Optional[FieldRecords] = OMIT,
tokenization: typing.Optional[bool] = OMIT,
- byot: typing.Optional[V1Byot] = OMIT,
+ byot: typing.Optional[UpdateRecordRequestByot] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> V1UpdateRecordResponse:
+ ) -> UpdateRecordResponse:
"""
Updates the specified record in a table.
When you update a field, include the entire contents you want the field to store. For JSON fields, include all nested fields and values. If a nested field isn't included, it's removed.
The time-to-live (TTL) for a transient field resets when the field value is updated.
Parameters
----------
vault_id : str
- ID of the vault.
object_name : str
- Name of the table.
id : str
- `skyflow_id` of the record.
- record : typing.Optional[V1FieldRecords]
+ record : typing.Optional[FieldRecords]
tokenization : typing.Optional[bool]
If `true`, this operation returns tokens for fields with tokenization enabled.
- byot : typing.Optional[V1Byot]
+ byot : typing.Optional[UpdateRecordRequestByot]
+ Token insertion behavior.
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- V1UpdateRecordResponse
- A successful response.
+ UpdateRecordResponse
+ OK
Examples
--------
import asyncio
- from skyflow import AsyncSkyflow, V1FieldRecords
+ from skyflow import AsyncSkyflowAuth, FieldRecords
- client = AsyncSkyflow(
+ client = AsyncSkyflowAuth(
token="YOUR_TOKEN",
)
async def main() -> None:
- await client.records.record_service_update_record(
+ await client.records.update_record(
vault_id="vaultID",
object_name="objectName",
id="ID",
- record=V1FieldRecords(
+ record=FieldRecords(
fields={
"drivers_license_number": "89867453",
"name": "Steve Smith",
@@ -1295,7 +1011,7 @@ async def main() -> None:
asyncio.run(main())
"""
- _response = await self._raw_client.record_service_update_record(
+ _response = await self._raw_client.update_record(
vault_id,
object_name,
id,
@@ -1306,9 +1022,9 @@ async def main() -> None:
)
return _response.data
- async def record_service_delete_record(
+ async def delete_record(
self, vault_id: str, object_name: str, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> V1DeleteRecordResponse:
+ ) -> DeleteRecordResponse:
"""
Deletes the specified record from a table.
Note: This method doesn't delete transient field tokens. Transient field values are available until they expire based on the fields' time-to-live (TTL) setting.
@@ -1328,22 +1044,22 @@ async def record_service_delete_record(
Returns
-------
- V1DeleteRecordResponse
- A successful response.
+ DeleteRecordResponse
+ OK
Examples
--------
import asyncio
- from skyflow import AsyncSkyflow
+ from skyflow import AsyncSkyflowAuth
- client = AsyncSkyflow(
+ client = AsyncSkyflowAuth(
token="YOUR_TOKEN",
)
async def main() -> None:
- await client.records.record_service_delete_record(
+ await client.records.delete_record(
vault_id="vaultID",
object_name="objectName",
id="ID",
@@ -1352,267 +1068,5 @@ async def main() -> None:
asyncio.run(main())
"""
- _response = await self._raw_client.record_service_delete_record(
- vault_id, object_name, id, request_options=request_options
- )
- return _response.data
-
- async def file_service_upload_file(
- self,
- vault_id: str,
- object_name: str,
- id: str,
- *,
- file: typing.Optional[core.File] = OMIT,
- column_name: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> V1UpdateRecordResponse:
- """
- Uploads a file to the specified record.
-
- Parameters
- ----------
- vault_id : str
- ID of the vault.
-
- object_name : str
- Name of the table.
-
- id : str
- `skyflow_id` of the record.
-
- file : typing.Optional[core.File]
- See core.File for more documentation
-
- column_name : typing.Optional[str]
- Name of the column to store the file in. The column must have a file data type.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- V1UpdateRecordResponse
- A successful response.
-
- Examples
- --------
- import asyncio
-
- from skyflow import AsyncSkyflow
-
- client = AsyncSkyflow(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.records.file_service_upload_file(
- vault_id="vaultID",
- object_name="objectName",
- id="ID",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._raw_client.file_service_upload_file(
- vault_id, object_name, id, file=file, column_name=column_name, request_options=request_options
- )
- return _response.data
-
- async def file_service_delete_file(
- self,
- vault_id: str,
- table_name: str,
- id: str,
- column_name: str,
- *,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> V1DeleteFileResponse:
- """
- Deletes a file from the specified record.
-
- Parameters
- ----------
- vault_id : str
- ID of the vault.
-
- table_name : str
- Name of the table.
-
- id : str
- `skyflow_id` of the record.
-
- column_name : str
- Name of the column that contains the file.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- V1DeleteFileResponse
- A successful response.
-
- Examples
- --------
- import asyncio
-
- from skyflow import AsyncSkyflow
-
- client = AsyncSkyflow(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.records.file_service_delete_file(
- vault_id="vaultID",
- table_name="tableName",
- id="ID",
- column_name="columnName",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._raw_client.file_service_delete_file(
- vault_id, table_name, id, column_name, request_options=request_options
- )
- return _response.data
-
- async def file_service_get_file_scan_status(
- self,
- vault_id: str,
- table_name: str,
- id: str,
- column_name: str,
- *,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> V1GetFileScanStatusResponse:
- """
- Returns the anti-virus scan status of a file.
-
- Parameters
- ----------
- vault_id : str
- ID of the vault.
-
- table_name : str
- Name of the table.
-
- id : str
- `skyflow_id` of the record.
-
- column_name : str
- Name of the column that contains the file.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- V1GetFileScanStatusResponse
- A successful response.
-
- Examples
- --------
- import asyncio
-
- from skyflow import AsyncSkyflow
-
- client = AsyncSkyflow(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.records.file_service_get_file_scan_status(
- vault_id="vaultID",
- table_name="tableName",
- id="ID",
- column_name="columnName",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._raw_client.file_service_get_file_scan_status(
- vault_id, table_name, id, column_name, request_options=request_options
- )
- return _response.data
-
- async def upload_file_v_2(
- self,
- vault_id: str,
- *,
- table_name: str,
- column_name: str,
- file: core.File,
- skyflow_id: typing.Optional[str] = OMIT,
- return_file_metadata: typing.Optional[bool] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> UploadFileV2Response:
- """
- Uploads the specified file to a record. If an existing record isn't specified, creates a new record and uploads the file to that record.
-
- Parameters
- ----------
- vault_id : str
- ID of the vault.
-
- table_name : str
- Name of the table to upload the file to.
-
- column_name : str
- Name of the column to upload the file to. The column must have a `file` data type.
-
- file : core.File
- See core.File for more documentation
-
- skyflow_id : typing.Optional[str]
- Skyflow ID of the record to upload the file to. If `skyflowID` isn't specified, a new record will be created.
-
- return_file_metadata : typing.Optional[bool]
- If `true`, returns metadata about the uploaded file.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- UploadFileV2Response
- File uploaded successfully.
-
- Examples
- --------
- import asyncio
-
- from skyflow import AsyncSkyflow
-
- client = AsyncSkyflow(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.records.upload_file_v_2(
- vault_id="d4410ea01d83473ca09a24c6b03096d4",
- table_name="tableName",
- column_name="columnName",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._raw_client.upload_file_v_2(
- vault_id,
- table_name=table_name,
- column_name=column_name,
- file=file,
- skyflow_id=skyflow_id,
- return_file_metadata=return_file_metadata,
- request_options=request_options,
- )
+ _response = await self._raw_client.delete_record(vault_id, object_name, id, request_options=request_options)
return _response.data
diff --git a/skyvault/skyflow/generated/rest/records/raw_client.py b/skyvault/skyflow/generated/rest/records/raw_client.py
index b42e0bc9..c3e3bf9c 100644
--- a/skyvault/skyflow/generated/rest/records/raw_client.py
+++ b/skyvault/skyflow/generated/rest/records/raw_client.py
@@ -3,11 +3,11 @@
import typing
from json.decoder import JSONDecodeError
-from .. import core
from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.http_response import AsyncHttpResponse, HttpResponse
-from ..core.jsonable_encoder import jsonable_encoder
+from ..core.jsonable_encoder import encode_path_param
+from ..core.parse_error import ParsingError
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
from ..core.serialization import convert_and_respect_annotation_metadata
@@ -15,22 +15,22 @@
from ..errors.internal_server_error import InternalServerError
from ..errors.not_found_error import NotFoundError
from ..errors.unauthorized_error import UnauthorizedError
+from ..types.batch_operation_response import BatchOperationResponse
+from ..types.batch_record import BatchRecord
+from ..types.bulk_delete_record_response import BulkDeleteRecordResponse
+from ..types.bulk_get_record_response import BulkGetRecordResponse
+from ..types.delete_record_response import DeleteRecordResponse
from ..types.error_response import ErrorResponse
-from ..types.upload_file_v_2_response import UploadFileV2Response
-from ..types.v_1_batch_operation_response import V1BatchOperationResponse
-from ..types.v_1_batch_record import V1BatchRecord
-from ..types.v_1_bulk_delete_record_response import V1BulkDeleteRecordResponse
-from ..types.v_1_bulk_get_record_response import V1BulkGetRecordResponse
-from ..types.v_1_byot import V1Byot
-from ..types.v_1_delete_file_response import V1DeleteFileResponse
-from ..types.v_1_delete_record_response import V1DeleteRecordResponse
-from ..types.v_1_field_records import V1FieldRecords
-from ..types.v_1_get_file_scan_status_response import V1GetFileScanStatusResponse
-from ..types.v_1_insert_record_response import V1InsertRecordResponse
-from ..types.v_1_update_record_response import V1UpdateRecordResponse
-from .types.record_service_bulk_get_record_request_order_by import RecordServiceBulkGetRecordRequestOrderBy
-from .types.record_service_bulk_get_record_request_redaction import RecordServiceBulkGetRecordRequestRedaction
-from .types.record_service_get_record_request_redaction import RecordServiceGetRecordRequestRedaction
+from ..types.field_records import FieldRecords
+from ..types.get_field_records import GetFieldRecords
+from ..types.insert_record_response import InsertRecordResponse
+from ..types.update_record_response import UpdateRecordResponse
+from .types.get_record_by_id_request_redaction import GetRecordByIdRequestRedaction
+from .types.get_records_request_order_by import GetRecordsRequestOrderBy
+from .types.get_records_request_redaction import GetRecordsRequestRedaction
+from .types.insert_record_request_byot import InsertRecordRequestByot
+from .types.update_record_request_byot import UpdateRecordRequestByot
+from pydantic import ValidationError
# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)
@@ -40,15 +40,14 @@ class RawRecordsClient:
def __init__(self, *, client_wrapper: SyncClientWrapper):
self._client_wrapper = client_wrapper
- def record_service_batch_operation(
+ def batch_operation(
self,
vault_id: str,
*,
- records: typing.Optional[typing.Sequence[V1BatchRecord]] = OMIT,
+ records: typing.Sequence[BatchRecord],
continue_on_error: typing.Optional[bool] = OMIT,
- byot: typing.Optional[V1Byot] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[V1BatchOperationResponse]:
+ ) -> HttpResponse[BatchOperationResponse]:
"""
Performs multiple record operations in a single transaction.
@@ -57,31 +56,28 @@ def record_service_batch_operation(
vault_id : str
ID of the vault.
- records : typing.Optional[typing.Sequence[V1BatchRecord]]
+ records : typing.Sequence[BatchRecord]
Record operations to perform.
continue_on_error : typing.Optional[bool]
- Continue performing operations on partial errors.
-
- byot : typing.Optional[V1Byot]
+ If `true`, continues processing remaining operations when one operation returns an error. If `false`, stops processing remaining operations when one operation returns an error.
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- HttpResponse[V1BatchOperationResponse]
- A successful response.
+ HttpResponse[BatchOperationResponse]
+ OK
"""
_response = self._client_wrapper.httpx_client.request(
- f"v1/vaults/{jsonable_encoder(vault_id)}",
+ f"v1/vaults/{encode_path_param(vault_id)}",
method="POST",
json={
"records": convert_and_respect_annotation_metadata(
- object_=records, annotation=typing.Sequence[V1BatchRecord], direction="write"
+ object_=records, annotation=typing.Sequence[BatchRecord], direction="write"
),
"continueOnError": continue_on_error,
- "byot": byot,
},
headers={
"content-type": "application/json",
@@ -92,20 +88,53 @@ def record_service_batch_operation(
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- V1BatchOperationResponse,
+ BatchOperationResponse,
parse_obj_as(
- type_=V1BatchOperationResponse, # type: ignore
+ type_=BatchOperationResponse, # type: ignore
object_=_response.json(),
),
)
return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 400:
+ raise BadRequestError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 401:
+ raise UnauthorizedError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
if _response.status_code == 404:
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 500:
+ raise InternalServerError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -113,15 +142,19 @@ def record_service_batch_operation(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
- def record_service_bulk_get_record(
+ def get_records(
self,
vault_id: str,
object_name: str,
*,
skyflow_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
- redaction: typing.Optional[RecordServiceBulkGetRecordRequestRedaction] = None,
+ redaction: typing.Optional[GetRecordsRequestRedaction] = None,
tokenization: typing.Optional[bool] = None,
fields: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
offset: typing.Optional[str] = None,
@@ -129,60 +162,51 @@ def record_service_bulk_get_record(
download_url: typing.Optional[bool] = None,
column_name: typing.Optional[str] = None,
column_values: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
- order_by: typing.Optional[RecordServiceBulkGetRecordRequestOrderBy] = None,
+ order_by: typing.Optional[GetRecordsRequestOrderBy] = None,
+ return_file_metadata: typing.Optional[bool] = None,
request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[V1BulkGetRecordResponse]:
+ ) -> HttpResponse[BulkGetRecordResponse]:
"""
- Gets the specified records from a table.
+ Returns the specified records from a table.
Parameters
----------
vault_id : str
- ID of the vault.
object_name : str
- Name of the table that contains the records.
skyflow_ids : typing.Optional[typing.Union[str, typing.Sequence[str]]]
- `skyflow_id` values of the records to return, with one value per `skyflow_ids` URL parameter. For example, `?skyflow_ids=abc&skyflow_ids=123`.
If not specified, returns the first 25 records in the table.
- redaction : typing.Optional[RecordServiceBulkGetRecordRequestRedaction]
- Redaction level to enforce for the returned records. Subject to policies assigned to the API caller.
+ redaction : typing.Optional[GetRecordsRequestRedaction]
tokenization : typing.Optional[bool]
- If `true`, this operation returns tokens for fields with tokenization enabled. Only applicable if `skyflow_id` values are specified.
fields : typing.Optional[typing.Union[str, typing.Sequence[str]]]
- Fields to return for the record, with one value per `fields` URL parameter. For example, `?fields=abc&fields=123`.
If not specified, returns all fields.
offset : typing.Optional[str]
- Record position at which to start receiving data.
limit : typing.Optional[str]
- Number of record to return. Maximum 25.
download_url : typing.Optional[bool]
- If `true`, returns download URLs for fields with a file data type. URLs are valid for 15 minutes. If virus scanning is enabled, only returns if the file is clean.
column_name : typing.Optional[str]
- Name of the column. It must be configured as unique in the schema. If you provide both column name or column value, you cannot use `skyflow_ids`. Passing either of these parameters with `skyflow_ids` returns an error.
column_values : typing.Optional[typing.Union[str, typing.Sequence[str]]]
- Column values of the records to return, with one value per `column_values` URL parameter. For example, `?column_values=abc&column_values=123`.
`column_name` is mandatory when providing `column_values`. If you use column name or column value, you cannot use `skyflow_ids`. Passing either of these parameters with `skyflow_ids` returns an error.
- order_by : typing.Optional[RecordServiceBulkGetRecordRequestOrderBy]
- Order to return records, based on `skyflow_id` values. To disable, set to `NONE`.
+ order_by : typing.Optional[GetRecordsRequestOrderBy]
+
+ return_file_metadata : typing.Optional[bool]
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- HttpResponse[V1BulkGetRecordResponse]
- A successful response.
+ HttpResponse[BulkGetRecordResponse]
+ OK
"""
_response = self._client_wrapper.httpx_client.request(
- f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}",
+ f"v1/vaults/{encode_path_param(vault_id)}/{encode_path_param(object_name)}",
method="GET",
params={
"skyflow_ids": skyflow_ids,
@@ -195,26 +219,60 @@ def record_service_bulk_get_record(
"column_name": column_name,
"column_values": column_values,
"order_by": order_by,
+ "returnFileMetadata": return_file_metadata,
},
request_options=request_options,
)
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- V1BulkGetRecordResponse,
+ BulkGetRecordResponse,
parse_obj_as(
- type_=V1BulkGetRecordResponse, # type: ignore
+ type_=BulkGetRecordResponse, # type: ignore
object_=_response.json(),
),
)
return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 400:
+ raise BadRequestError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 401:
+ raise UnauthorizedError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
if _response.status_code == 404:
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 500:
+ raise InternalServerError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -222,32 +280,34 @@ def record_service_bulk_get_record(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
- def record_service_insert_record(
+ def insert_records(
self,
vault_id: str,
object_name: str,
*,
- records: typing.Optional[typing.Sequence[V1FieldRecords]] = OMIT,
+ records: typing.Sequence[FieldRecords],
tokenization: typing.Optional[bool] = OMIT,
upsert: typing.Optional[str] = OMIT,
homogeneous: typing.Optional[bool] = OMIT,
- byot: typing.Optional[V1Byot] = OMIT,
+ byot: typing.Optional[InsertRecordRequestByot] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[V1InsertRecordResponse]:
+ ) -> HttpResponse[InsertRecordResponse]:
"""
Inserts a record in the specified table.
The time-to-live (TTL) for a transient field begins when the field value is set during record insertion.
Columns that have a string data type and a uniqueness constraint accept strings up to 2500 characters. If an inserted string exceeds 2500 characters, the call returns a token insertion error.
Parameters
----------
vault_id : str
- ID of the vault.
object_name : str
- Name of the table.
- records : typing.Optional[typing.Sequence[V1FieldRecords]]
+ records : typing.Sequence[FieldRecords]
Record values and tokens.
tokenization : typing.Optional[bool]
@@ -259,22 +319,23 @@ def record_service_insert_record(
homogeneous : typing.Optional[bool]
If `true`, this operation mandates that all the records have the same fields. This parameter does not work with upsert.
- byot : typing.Optional[V1Byot]
+ byot : typing.Optional[InsertRecordRequestByot]
+ Token insertion behavior.
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- HttpResponse[V1InsertRecordResponse]
- A successful response.
+ HttpResponse[InsertRecordResponse]
+ OK
"""
_response = self._client_wrapper.httpx_client.request(
- f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}",
+ f"v1/vaults/{encode_path_param(vault_id)}/{encode_path_param(object_name)}",
method="POST",
json={
"records": convert_and_respect_annotation_metadata(
- object_=records, annotation=typing.Sequence[V1FieldRecords], direction="write"
+ object_=records, annotation=typing.Sequence[FieldRecords], direction="write"
),
"tokenization": tokenization,
"upsert": upsert,
@@ -290,20 +351,42 @@ def record_service_insert_record(
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- V1InsertRecordResponse,
+ InsertRecordResponse,
parse_obj_as(
- type_=V1InsertRecordResponse, # type: ignore
+ type_=InsertRecordResponse, # type: ignore
object_=_response.json(),
),
)
return HttpResponse(response=_response, data=_data)
- if _response.status_code == 404:
- raise NotFoundError(
+ if _response.status_code == 400:
+ raise BadRequestError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 401:
+ raise UnauthorizedError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 500:
+ raise InternalServerError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -311,16 +394,20 @@ def record_service_insert_record(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
- def record_service_bulk_delete_record(
+ def delete_records(
self,
vault_id: str,
object_name: str,
*,
skyflow_ids: typing.Optional[typing.Sequence[str]] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[V1BulkDeleteRecordResponse]:
+ ) -> HttpResponse[BulkDeleteRecordResponse]:
"""
Deletes the specified records from a table.
@@ -340,11 +427,11 @@ def record_service_bulk_delete_record(
Returns
-------
- HttpResponse[V1BulkDeleteRecordResponse]
- A successful response.
+ HttpResponse[BulkDeleteRecordResponse]
+ OK
"""
_response = self._client_wrapper.httpx_client.request(
- f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}",
+ f"v1/vaults/{encode_path_param(vault_id)}/{encode_path_param(object_name)}",
method="DELETE",
json={
"skyflow_ids": skyflow_ids,
@@ -358,20 +445,53 @@ def record_service_bulk_delete_record(
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- V1BulkDeleteRecordResponse,
+ BulkDeleteRecordResponse,
parse_obj_as(
- type_=V1BulkDeleteRecordResponse, # type: ignore
+ type_=BulkDeleteRecordResponse, # type: ignore
object_=_response.json(),
),
)
return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 400:
+ raise BadRequestError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 401:
+ raise UnauthorizedError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
if _response.status_code == 404:
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 500:
+ raise InternalServerError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -379,82 +499,116 @@ def record_service_bulk_delete_record(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
- def record_service_get_record(
+ def get_record_by_id(
self,
vault_id: str,
object_name: str,
id: str,
*,
- redaction: typing.Optional[RecordServiceGetRecordRequestRedaction] = None,
+ redaction: typing.Optional[GetRecordByIdRequestRedaction] = None,
tokenization: typing.Optional[bool] = None,
fields: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
download_url: typing.Optional[bool] = None,
+ return_file_metadata: typing.Optional[bool] = None,
request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[V1FieldRecords]:
+ ) -> HttpResponse[GetFieldRecords]:
"""
Returns the specified record from a table.
Parameters
----------
vault_id : str
- ID of the vault.
object_name : str
- Name of the table.
id : str
- `skyflow_id` of the record.
- redaction : typing.Optional[RecordServiceGetRecordRequestRedaction]
- Redaction level to enforce for the returned record. Subject to policies assigned to the API caller.
+ redaction : typing.Optional[GetRecordByIdRequestRedaction]
tokenization : typing.Optional[bool]
- If `true`, this operation returns tokens for fields with tokenization enabled. Only applicable if `skyflow_id` values are specified.
fields : typing.Optional[typing.Union[str, typing.Sequence[str]]]
- Fields to return for the record, with one value per `fields` URL parameter. For example, `?fields=abc&fields=123`.
If not specified, returns all fields.
download_url : typing.Optional[bool]
- If `true`, returns download URLs for fields with a file data type. URLs are valid for 15 minutes. If virus scanning is enabled, only returns if the file is clean.
+
+ return_file_metadata : typing.Optional[bool]
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- HttpResponse[V1FieldRecords]
- A successful response.
+ HttpResponse[GetFieldRecords]
+ OK
"""
_response = self._client_wrapper.httpx_client.request(
- f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}/{jsonable_encoder(id)}",
+ f"v1/vaults/{encode_path_param(vault_id)}/{encode_path_param(object_name)}/{encode_path_param(id)}",
method="GET",
params={
"redaction": redaction,
"tokenization": tokenization,
"fields": fields,
"downloadURL": download_url,
+ "returnFileMetadata": return_file_metadata,
},
request_options=request_options,
)
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- V1FieldRecords,
+ GetFieldRecords,
parse_obj_as(
- type_=V1FieldRecords, # type: ignore
+ type_=GetFieldRecords, # type: ignore
object_=_response.json(),
),
)
return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 400:
+ raise BadRequestError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 401:
+ raise UnauthorizedError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
if _response.status_code == 404:
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 500:
+ raise InternalServerError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -462,54 +616,56 @@ def record_service_get_record(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
- def record_service_update_record(
+ def update_record(
self,
vault_id: str,
object_name: str,
id: str,
*,
- record: typing.Optional[V1FieldRecords] = OMIT,
+ record: typing.Optional[FieldRecords] = OMIT,
tokenization: typing.Optional[bool] = OMIT,
- byot: typing.Optional[V1Byot] = OMIT,
+ byot: typing.Optional[UpdateRecordRequestByot] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[V1UpdateRecordResponse]:
+ ) -> HttpResponse[UpdateRecordResponse]:
"""
Updates the specified record in a table.
When you update a field, include the entire contents you want the field to store. For JSON fields, include all nested fields and values. If a nested field isn't included, it's removed.
The time-to-live (TTL) for a transient field resets when the field value is updated.
Parameters
----------
vault_id : str
- ID of the vault.
object_name : str
- Name of the table.
id : str
- `skyflow_id` of the record.
- record : typing.Optional[V1FieldRecords]
+ record : typing.Optional[FieldRecords]
tokenization : typing.Optional[bool]
If `true`, this operation returns tokens for fields with tokenization enabled.
- byot : typing.Optional[V1Byot]
+ byot : typing.Optional[UpdateRecordRequestByot]
+ Token insertion behavior.
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- HttpResponse[V1UpdateRecordResponse]
- A successful response.
+ HttpResponse[UpdateRecordResponse]
+ OK
"""
_response = self._client_wrapper.httpx_client.request(
- f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}/{jsonable_encoder(id)}",
+ f"v1/vaults/{encode_path_param(vault_id)}/{encode_path_param(object_name)}/{encode_path_param(id)}",
method="PUT",
json={
"record": convert_and_respect_annotation_metadata(
- object_=record, annotation=V1FieldRecords, direction="write"
+ object_=record, annotation=FieldRecords, direction="write"
),
"tokenization": tokenization,
"byot": byot,
@@ -523,20 +679,53 @@ def record_service_update_record(
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- V1UpdateRecordResponse,
+ UpdateRecordResponse,
parse_obj_as(
- type_=V1UpdateRecordResponse, # type: ignore
+ type_=UpdateRecordResponse, # type: ignore
object_=_response.json(),
),
)
return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 400:
+ raise BadRequestError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 401:
+ raise UnauthorizedError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
if _response.status_code == 404:
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 500:
+ raise InternalServerError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -544,11 +733,15 @@ def record_service_update_record(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
- def record_service_delete_record(
+ def delete_record(
self, vault_id: str, object_name: str, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> HttpResponse[V1DeleteRecordResponse]:
+ ) -> HttpResponse[DeleteRecordResponse]:
"""
Deletes the specified record from a table.
Note: This method doesn't delete transient field tokens. Transient field values are available until they expire based on the fields' time-to-live (TTL) setting.
@@ -568,31 +761,64 @@ def record_service_delete_record(
Returns
-------
- HttpResponse[V1DeleteRecordResponse]
- A successful response.
+ HttpResponse[DeleteRecordResponse]
+ OK
"""
_response = self._client_wrapper.httpx_client.request(
- f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}/{jsonable_encoder(id)}",
+ f"v1/vaults/{encode_path_param(vault_id)}/{encode_path_param(object_name)}/{encode_path_param(id)}",
method="DELETE",
request_options=request_options,
)
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- V1DeleteRecordResponse,
+ DeleteRecordResponse,
parse_obj_as(
- type_=V1DeleteRecordResponse, # type: ignore
+ type_=DeleteRecordResponse, # type: ignore
object_=_response.json(),
),
)
return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 400:
+ raise BadRequestError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 401:
+ raise UnauthorizedError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
if _response.status_code == 404:
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 500:
+ raise InternalServerError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -600,290 +826,79 @@ def record_service_delete_record(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
- def file_service_upload_file(
- self,
- vault_id: str,
- object_name: str,
- id: str,
- *,
- file: typing.Optional[core.File] = OMIT,
- column_name: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[V1UpdateRecordResponse]:
- """
- Uploads a file to the specified record.
-
- Parameters
- ----------
- vault_id : str
- ID of the vault.
-
- object_name : str
- Name of the table.
-
- id : str
- `skyflow_id` of the record.
-
- file : typing.Optional[core.File]
- See core.File for more documentation
-
- column_name : typing.Optional[str]
- Name of the column to store the file in. The column must have a file data type.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- HttpResponse[V1UpdateRecordResponse]
- A successful response.
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}/{jsonable_encoder(id)}/files",
- method="POST",
- data={
- "columnName": column_name,
- },
- files={
- **({"file": file} if file is not None else {}),
- },
- request_options=request_options,
- omit=OMIT,
- force_multipart=True,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- V1UpdateRecordResponse,
- parse_obj_as(
- type_=V1UpdateRecordResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return HttpResponse(response=_response, data=_data)
- if _response.status_code == 404:
- raise NotFoundError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
- def file_service_delete_file(
- self,
- vault_id: str,
- table_name: str,
- id: str,
- column_name: str,
- *,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[V1DeleteFileResponse]:
- """
- Deletes a file from the specified record.
-
- Parameters
- ----------
- vault_id : str
- ID of the vault.
-
- table_name : str
- Name of the table.
-
- id : str
- `skyflow_id` of the record.
-
- column_name : str
- Name of the column that contains the file.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- HttpResponse[V1DeleteFileResponse]
- A successful response.
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(table_name)}/{jsonable_encoder(id)}/files/{jsonable_encoder(column_name)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- V1DeleteFileResponse,
- parse_obj_as(
- type_=V1DeleteFileResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return HttpResponse(response=_response, data=_data)
- if _response.status_code == 404:
- raise NotFoundError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
- def file_service_get_file_scan_status(
- self,
- vault_id: str,
- table_name: str,
- id: str,
- column_name: str,
- *,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[V1GetFileScanStatusResponse]:
- """
- Returns the anti-virus scan status of a file.
-
- Parameters
- ----------
- vault_id : str
- ID of the vault.
-
- table_name : str
- Name of the table.
-
- id : str
- `skyflow_id` of the record.
-
- column_name : str
- Name of the column that contains the file.
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- HttpResponse[V1GetFileScanStatusResponse]
- A successful response.
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(table_name)}/{jsonable_encoder(id)}/files/{jsonable_encoder(column_name)}/scan-status",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- V1GetFileScanStatusResponse,
- parse_obj_as(
- type_=V1GetFileScanStatusResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return HttpResponse(response=_response, data=_data)
- if _response.status_code == 404:
- raise NotFoundError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
+class AsyncRawRecordsClient:
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
+ self._client_wrapper = client_wrapper
- def upload_file_v_2(
+ async def batch_operation(
self,
vault_id: str,
*,
- table_name: str,
- column_name: str,
- file: core.File,
- skyflow_id: typing.Optional[str] = OMIT,
- return_file_metadata: typing.Optional[bool] = OMIT,
+ records: typing.Sequence[BatchRecord],
+ continue_on_error: typing.Optional[bool] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[UploadFileV2Response]:
+ ) -> AsyncHttpResponse[BatchOperationResponse]:
"""
- Uploads the specified file to a record. If an existing record isn't specified, creates a new record and uploads the file to that record.
+ Performs multiple record operations in a single transaction.
Parameters
----------
vault_id : str
ID of the vault.
- table_name : str
- Name of the table to upload the file to.
-
- column_name : str
- Name of the column to upload the file to. The column must have a `file` data type.
-
- file : core.File
- See core.File for more documentation
-
- skyflow_id : typing.Optional[str]
- Skyflow ID of the record to upload the file to. If `skyflowID` isn't specified, a new record will be created.
+ records : typing.Sequence[BatchRecord]
+ Record operations to perform.
- return_file_metadata : typing.Optional[bool]
- If `true`, returns metadata about the uploaded file.
+ continue_on_error : typing.Optional[bool]
+ If `true`, continues processing remaining operations when one operation returns an error. If `false`, stops processing remaining operations when one operation returns an error.
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- HttpResponse[UploadFileV2Response]
- File uploaded successfully.
+ AsyncHttpResponse[BatchOperationResponse]
+ OK
"""
- _response = self._client_wrapper.httpx_client.request(
- f"v2/vaults/{jsonable_encoder(vault_id)}/files/upload",
+ _response = await self._client_wrapper.httpx_client.request(
+ f"v1/vaults/{encode_path_param(vault_id)}",
method="POST",
- data={
- "tableName": table_name,
- "columnName": column_name,
- "skyflowID": skyflow_id,
- "returnFileMetadata": return_file_metadata,
+ json={
+ "records": convert_and_respect_annotation_metadata(
+ object_=records, annotation=typing.Sequence[BatchRecord], direction="write"
+ ),
+ "continueOnError": continue_on_error,
},
- files={
- "file": file,
+ headers={
+ "content-type": "application/json",
},
request_options=request_options,
omit=OMIT,
- force_multipart=True,
)
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- UploadFileV2Response,
+ BatchOperationResponse,
parse_obj_as(
- type_=UploadFileV2Response, # type: ignore
+ type_=BatchOperationResponse, # type: ignore
object_=_response.json(),
),
)
- return HttpResponse(response=_response, data=_data)
+ return AsyncHttpResponse(response=_response, data=_data)
if _response.status_code == 400:
raise BadRequestError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -892,9 +907,9 @@ def upload_file_v_2(
raise UnauthorizedError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -903,9 +918,9 @@ def upload_file_v_2(
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -924,95 +939,19 @@ def upload_file_v_2(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
-class AsyncRawRecordsClient:
- def __init__(self, *, client_wrapper: AsyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- async def record_service_batch_operation(
- self,
- vault_id: str,
- *,
- records: typing.Optional[typing.Sequence[V1BatchRecord]] = OMIT,
- continue_on_error: typing.Optional[bool] = OMIT,
- byot: typing.Optional[V1Byot] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[V1BatchOperationResponse]:
- """
- Performs multiple record operations in a single transaction.
-
- Parameters
- ----------
- vault_id : str
- ID of the vault.
-
- records : typing.Optional[typing.Sequence[V1BatchRecord]]
- Record operations to perform.
-
- continue_on_error : typing.Optional[bool]
- Continue performing operations on partial errors.
-
- byot : typing.Optional[V1Byot]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AsyncHttpResponse[V1BatchOperationResponse]
- A successful response.
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/vaults/{jsonable_encoder(vault_id)}",
- method="POST",
- json={
- "records": convert_and_respect_annotation_metadata(
- object_=records, annotation=typing.Sequence[V1BatchRecord], direction="write"
- ),
- "continueOnError": continue_on_error,
- "byot": byot,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- V1BatchOperationResponse,
- parse_obj_as(
- type_=V1BatchOperationResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return AsyncHttpResponse(response=_response, data=_data)
- if _response.status_code == 404:
- raise NotFoundError(
- headers=dict(_response.headers),
- body=typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- ),
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
- async def record_service_bulk_get_record(
+ async def get_records(
self,
vault_id: str,
object_name: str,
*,
skyflow_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
- redaction: typing.Optional[RecordServiceBulkGetRecordRequestRedaction] = None,
+ redaction: typing.Optional[GetRecordsRequestRedaction] = None,
tokenization: typing.Optional[bool] = None,
fields: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
offset: typing.Optional[str] = None,
@@ -1020,60 +959,51 @@ async def record_service_bulk_get_record(
download_url: typing.Optional[bool] = None,
column_name: typing.Optional[str] = None,
column_values: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
- order_by: typing.Optional[RecordServiceBulkGetRecordRequestOrderBy] = None,
+ order_by: typing.Optional[GetRecordsRequestOrderBy] = None,
+ return_file_metadata: typing.Optional[bool] = None,
request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[V1BulkGetRecordResponse]:
+ ) -> AsyncHttpResponse[BulkGetRecordResponse]:
"""
- Gets the specified records from a table.
+ Returns the specified records from a table.
Parameters
----------
vault_id : str
- ID of the vault.
object_name : str
- Name of the table that contains the records.
skyflow_ids : typing.Optional[typing.Union[str, typing.Sequence[str]]]
- `skyflow_id` values of the records to return, with one value per `skyflow_ids` URL parameter. For example, `?skyflow_ids=abc&skyflow_ids=123`.
If not specified, returns the first 25 records in the table.
- redaction : typing.Optional[RecordServiceBulkGetRecordRequestRedaction]
- Redaction level to enforce for the returned records. Subject to policies assigned to the API caller.
+ redaction : typing.Optional[GetRecordsRequestRedaction]
tokenization : typing.Optional[bool]
- If `true`, this operation returns tokens for fields with tokenization enabled. Only applicable if `skyflow_id` values are specified.
fields : typing.Optional[typing.Union[str, typing.Sequence[str]]]
- Fields to return for the record, with one value per `fields` URL parameter. For example, `?fields=abc&fields=123`.
If not specified, returns all fields.
offset : typing.Optional[str]
- Record position at which to start receiving data.
limit : typing.Optional[str]
- Number of record to return. Maximum 25.
download_url : typing.Optional[bool]
- If `true`, returns download URLs for fields with a file data type. URLs are valid for 15 minutes. If virus scanning is enabled, only returns if the file is clean.
column_name : typing.Optional[str]
- Name of the column. It must be configured as unique in the schema. If you provide both column name or column value, you cannot use `skyflow_ids`. Passing either of these parameters with `skyflow_ids` returns an error.
column_values : typing.Optional[typing.Union[str, typing.Sequence[str]]]
- Column values of the records to return, with one value per `column_values` URL parameter. For example, `?column_values=abc&column_values=123`.
`column_name` is mandatory when providing `column_values`. If you use column name or column value, you cannot use `skyflow_ids`. Passing either of these parameters with `skyflow_ids` returns an error.
- order_by : typing.Optional[RecordServiceBulkGetRecordRequestOrderBy]
- Order to return records, based on `skyflow_id` values. To disable, set to `NONE`.
+ order_by : typing.Optional[GetRecordsRequestOrderBy]
+
+ return_file_metadata : typing.Optional[bool]
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- AsyncHttpResponse[V1BulkGetRecordResponse]
- A successful response.
+ AsyncHttpResponse[BulkGetRecordResponse]
+ OK
"""
_response = await self._client_wrapper.httpx_client.request(
- f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}",
+ f"v1/vaults/{encode_path_param(vault_id)}/{encode_path_param(object_name)}",
method="GET",
params={
"skyflow_ids": skyflow_ids,
@@ -1086,266 +1016,60 @@ async def record_service_bulk_get_record(
"column_name": column_name,
"column_values": column_values,
"order_by": order_by,
+ "returnFileMetadata": return_file_metadata,
},
request_options=request_options,
)
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- V1BulkGetRecordResponse,
+ BulkGetRecordResponse,
parse_obj_as(
- type_=V1BulkGetRecordResponse, # type: ignore
+ type_=BulkGetRecordResponse, # type: ignore
object_=_response.json(),
),
)
return AsyncHttpResponse(response=_response, data=_data)
- if _response.status_code == 404:
- raise NotFoundError(
+ if _response.status_code == 400:
+ raise BadRequestError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
)
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
- async def record_service_insert_record(
- self,
- vault_id: str,
- object_name: str,
- *,
- records: typing.Optional[typing.Sequence[V1FieldRecords]] = OMIT,
- tokenization: typing.Optional[bool] = OMIT,
- upsert: typing.Optional[str] = OMIT,
- homogeneous: typing.Optional[bool] = OMIT,
- byot: typing.Optional[V1Byot] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[V1InsertRecordResponse]:
- """
- Inserts a record in the specified table.
The time-to-live (TTL) for a transient field begins when the field value is set during record insertion.
Columns that have a string data type and a uniqueness constraint accept strings up to 2500 characters. If an inserted string exceeds 2500 characters, the call returns a token insertion error.
-
- Parameters
- ----------
- vault_id : str
- ID of the vault.
-
- object_name : str
- Name of the table.
-
- records : typing.Optional[typing.Sequence[V1FieldRecords]]
- Record values and tokens.
-
- tokenization : typing.Optional[bool]
- If `true`, this operation returns tokens for fields with tokenization enabled.
-
- upsert : typing.Optional[str]
- Name of a unique column in the table. Uses upsert operations to check if a record exists based on the unique column's value. If a matching record exists, the record updates with the values you provide. If a matching record doesn't exist, the upsert operation inserts a new record.
When you upsert a field, include the entire contents you want the field to store. For JSON fields, include all nested fields and values. If a nested field isn't included, it's removed.
-
- homogeneous : typing.Optional[bool]
- If `true`, this operation mandates that all the records have the same fields. This parameter does not work with upsert.
-
- byot : typing.Optional[V1Byot]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AsyncHttpResponse[V1InsertRecordResponse]
- A successful response.
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}",
- method="POST",
- json={
- "records": convert_and_respect_annotation_metadata(
- object_=records, annotation=typing.Sequence[V1FieldRecords], direction="write"
- ),
- "tokenization": tokenization,
- "upsert": upsert,
- "homogeneous": homogeneous,
- "byot": byot,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- V1InsertRecordResponse,
- parse_obj_as(
- type_=V1InsertRecordResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return AsyncHttpResponse(response=_response, data=_data)
- if _response.status_code == 404:
- raise NotFoundError(
+ if _response.status_code == 401:
+ raise UnauthorizedError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
)
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
- async def record_service_bulk_delete_record(
- self,
- vault_id: str,
- object_name: str,
- *,
- skyflow_ids: typing.Optional[typing.Sequence[str]] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[V1BulkDeleteRecordResponse]:
- """
- Deletes the specified records from a table.
-
- Parameters
- ----------
- vault_id : str
- ID of the vault.
-
- object_name : str
- Name of the table.
-
- skyflow_ids : typing.Optional[typing.Sequence[str]]
- `skyflow_id` values of the records to delete. If `*` is specified, this operation deletes all records in the table.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AsyncHttpResponse[V1BulkDeleteRecordResponse]
- A successful response.
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}",
- method="DELETE",
- json={
- "skyflow_ids": skyflow_ids,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- V1BulkDeleteRecordResponse,
- parse_obj_as(
- type_=V1BulkDeleteRecordResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- return AsyncHttpResponse(response=_response, data=_data)
if _response.status_code == 404:
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
)
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
- async def record_service_get_record(
- self,
- vault_id: str,
- object_name: str,
- id: str,
- *,
- redaction: typing.Optional[RecordServiceGetRecordRequestRedaction] = None,
- tokenization: typing.Optional[bool] = None,
- fields: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
- download_url: typing.Optional[bool] = None,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[V1FieldRecords]:
- """
- Returns the specified record from a table.
-
- Parameters
- ----------
- vault_id : str
- ID of the vault.
-
- object_name : str
- Name of the table.
-
- id : str
- `skyflow_id` of the record.
-
- redaction : typing.Optional[RecordServiceGetRecordRequestRedaction]
- Redaction level to enforce for the returned record. Subject to policies assigned to the API caller.
-
- tokenization : typing.Optional[bool]
- If `true`, this operation returns tokens for fields with tokenization enabled. Only applicable if `skyflow_id` values are specified.
-
- fields : typing.Optional[typing.Union[str, typing.Sequence[str]]]
- Fields to return for the record, with one value per `fields` URL parameter. For example, `?fields=abc&fields=123`.
If not specified, returns all fields.
-
- download_url : typing.Optional[bool]
- If `true`, returns download URLs for fields with a file data type. URLs are valid for 15 minutes. If virus scanning is enabled, only returns if the file is clean.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AsyncHttpResponse[V1FieldRecords]
- A successful response.
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}/{jsonable_encoder(id)}",
- method="GET",
- params={
- "redaction": redaction,
- "tokenization": tokenization,
- "fields": fields,
- "downloadURL": download_url,
- },
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- V1FieldRecords,
- parse_obj_as(
- type_=V1FieldRecords, # type: ignore
- object_=_response.json(),
- ),
- )
- return AsyncHttpResponse(response=_response, data=_data)
- if _response.status_code == 404:
- raise NotFoundError(
+ if _response.status_code == 500:
+ raise InternalServerError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -1353,56 +1077,66 @@ async def record_service_get_record(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
- async def record_service_update_record(
+ async def insert_records(
self,
vault_id: str,
object_name: str,
- id: str,
*,
- record: typing.Optional[V1FieldRecords] = OMIT,
+ records: typing.Sequence[FieldRecords],
tokenization: typing.Optional[bool] = OMIT,
- byot: typing.Optional[V1Byot] = OMIT,
+ upsert: typing.Optional[str] = OMIT,
+ homogeneous: typing.Optional[bool] = OMIT,
+ byot: typing.Optional[InsertRecordRequestByot] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[V1UpdateRecordResponse]:
+ ) -> AsyncHttpResponse[InsertRecordResponse]:
"""
- Updates the specified record in a table.
When you update a field, include the entire contents you want the field to store. For JSON fields, include all nested fields and values. If a nested field isn't included, it's removed.
The time-to-live (TTL) for a transient field resets when the field value is updated.
+ Inserts a record in the specified table.
The time-to-live (TTL) for a transient field begins when the field value is set during record insertion.
Columns that have a string data type and a uniqueness constraint accept strings up to 2500 characters. If an inserted string exceeds 2500 characters, the call returns a token insertion error.
Parameters
----------
vault_id : str
- ID of the vault.
object_name : str
- Name of the table.
-
- id : str
- `skyflow_id` of the record.
- record : typing.Optional[V1FieldRecords]
+ records : typing.Sequence[FieldRecords]
+ Record values and tokens.
tokenization : typing.Optional[bool]
If `true`, this operation returns tokens for fields with tokenization enabled.
- byot : typing.Optional[V1Byot]
+ upsert : typing.Optional[str]
+ Name of a unique column in the table. Uses upsert operations to check if a record exists based on the unique column's value. If a matching record exists, the record updates with the values you provide. If a matching record doesn't exist, the upsert operation inserts a new record.
When you upsert a field, include the entire contents you want the field to store. For JSON fields, include all nested fields and values. If a nested field isn't included, it's removed.
+
+ homogeneous : typing.Optional[bool]
+ If `true`, this operation mandates that all the records have the same fields. This parameter does not work with upsert.
+
+ byot : typing.Optional[InsertRecordRequestByot]
+ Token insertion behavior.
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- AsyncHttpResponse[V1UpdateRecordResponse]
- A successful response.
+ AsyncHttpResponse[InsertRecordResponse]
+ OK
"""
_response = await self._client_wrapper.httpx_client.request(
- f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}/{jsonable_encoder(id)}",
- method="PUT",
+ f"v1/vaults/{encode_path_param(vault_id)}/{encode_path_param(object_name)}",
+ method="POST",
json={
- "record": convert_and_respect_annotation_metadata(
- object_=record, annotation=V1FieldRecords, direction="write"
+ "records": convert_and_respect_annotation_metadata(
+ object_=records, annotation=typing.Sequence[FieldRecords], direction="write"
),
"tokenization": tokenization,
+ "upsert": upsert,
+ "homogeneous": homogeneous,
"byot": byot,
},
headers={
@@ -1414,76 +1148,42 @@ async def record_service_update_record(
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- V1UpdateRecordResponse,
+ InsertRecordResponse,
parse_obj_as(
- type_=V1UpdateRecordResponse, # type: ignore
+ type_=InsertRecordResponse, # type: ignore
object_=_response.json(),
),
)
return AsyncHttpResponse(response=_response, data=_data)
- if _response.status_code == 404:
- raise NotFoundError(
+ if _response.status_code == 400:
+ raise BadRequestError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
)
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
- raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
-
- async def record_service_delete_record(
- self, vault_id: str, object_name: str, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> AsyncHttpResponse[V1DeleteRecordResponse]:
- """
- Deletes the specified record from a table.
Note: This method doesn't delete transient field tokens. Transient field values are available until they expire based on the fields' time-to-live (TTL) setting.
-
- Parameters
- ----------
- vault_id : str
- ID of the vault.
-
- object_name : str
- Name of the table.
-
- id : str
- `skyflow_id` of the record to delete.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AsyncHttpResponse[V1DeleteRecordResponse]
- A successful response.
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}/{jsonable_encoder(id)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- _data = typing.cast(
- V1DeleteRecordResponse,
- parse_obj_as(
- type_=V1DeleteRecordResponse, # type: ignore
- object_=_response.json(),
+ if _response.status_code == 401:
+ raise UnauthorizedError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
),
)
- return AsyncHttpResponse(response=_response, data=_data)
- if _response.status_code == 404:
- raise NotFoundError(
+ if _response.status_code == 500:
+ raise InternalServerError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -1491,20 +1191,22 @@ async def record_service_delete_record(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
- async def file_service_upload_file(
+ async def delete_records(
self,
vault_id: str,
object_name: str,
- id: str,
*,
- file: typing.Optional[core.File] = OMIT,
- column_name: typing.Optional[str] = OMIT,
+ skyflow_ids: typing.Optional[typing.Sequence[str]] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[V1UpdateRecordResponse]:
+ ) -> AsyncHttpResponse[BulkDeleteRecordResponse]:
"""
- Uploads a file to the specified record.
+ Deletes the specified records from a table.
Parameters
----------
@@ -1514,53 +1216,79 @@ async def file_service_upload_file(
object_name : str
Name of the table.
- id : str
- `skyflow_id` of the record.
-
- file : typing.Optional[core.File]
- See core.File for more documentation
-
- column_name : typing.Optional[str]
- Name of the column to store the file in. The column must have a file data type.
+ skyflow_ids : typing.Optional[typing.Sequence[str]]
+ `skyflow_id` values of the records to delete. If `*` is specified, this operation deletes all records in the table.
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- AsyncHttpResponse[V1UpdateRecordResponse]
- A successful response.
+ AsyncHttpResponse[BulkDeleteRecordResponse]
+ OK
"""
_response = await self._client_wrapper.httpx_client.request(
- f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(object_name)}/{jsonable_encoder(id)}/files",
- method="POST",
- data={
- "columnName": column_name,
+ f"v1/vaults/{encode_path_param(vault_id)}/{encode_path_param(object_name)}",
+ method="DELETE",
+ json={
+ "skyflow_ids": skyflow_ids,
},
- files={
- **({"file": file} if file is not None else {}),
+ headers={
+ "content-type": "application/json",
},
request_options=request_options,
omit=OMIT,
- force_multipart=True,
)
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- V1UpdateRecordResponse,
+ BulkDeleteRecordResponse,
parse_obj_as(
- type_=V1UpdateRecordResponse, # type: ignore
+ type_=BulkDeleteRecordResponse, # type: ignore
object_=_response.json(),
),
)
return AsyncHttpResponse(response=_response, data=_data)
+ if _response.status_code == 400:
+ raise BadRequestError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 401:
+ raise UnauthorizedError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
if _response.status_code == 404:
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 500:
+ raise InternalServerError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -1568,64 +1296,116 @@ async def file_service_upload_file(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
- async def file_service_delete_file(
+ async def get_record_by_id(
self,
vault_id: str,
- table_name: str,
+ object_name: str,
id: str,
- column_name: str,
*,
+ redaction: typing.Optional[GetRecordByIdRequestRedaction] = None,
+ tokenization: typing.Optional[bool] = None,
+ fields: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None,
+ download_url: typing.Optional[bool] = None,
+ return_file_metadata: typing.Optional[bool] = None,
request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[V1DeleteFileResponse]:
+ ) -> AsyncHttpResponse[GetFieldRecords]:
"""
- Deletes a file from the specified record.
+ Returns the specified record from a table.
Parameters
----------
vault_id : str
- ID of the vault.
- table_name : str
- Name of the table.
+ object_name : str
id : str
- `skyflow_id` of the record.
- column_name : str
- Name of the column that contains the file.
+ redaction : typing.Optional[GetRecordByIdRequestRedaction]
+
+ tokenization : typing.Optional[bool]
+
+ fields : typing.Optional[typing.Union[str, typing.Sequence[str]]]
+
+ download_url : typing.Optional[bool]
+
+ return_file_metadata : typing.Optional[bool]
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- AsyncHttpResponse[V1DeleteFileResponse]
- A successful response.
+ AsyncHttpResponse[GetFieldRecords]
+ OK
"""
_response = await self._client_wrapper.httpx_client.request(
- f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(table_name)}/{jsonable_encoder(id)}/files/{jsonable_encoder(column_name)}",
- method="DELETE",
+ f"v1/vaults/{encode_path_param(vault_id)}/{encode_path_param(object_name)}/{encode_path_param(id)}",
+ method="GET",
+ params={
+ "redaction": redaction,
+ "tokenization": tokenization,
+ "fields": fields,
+ "downloadURL": download_url,
+ "returnFileMetadata": return_file_metadata,
+ },
request_options=request_options,
)
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- V1DeleteFileResponse,
+ GetFieldRecords,
parse_obj_as(
- type_=V1DeleteFileResponse, # type: ignore
+ type_=GetFieldRecords, # type: ignore
object_=_response.json(),
),
)
return AsyncHttpResponse(response=_response, data=_data)
+ if _response.status_code == 400:
+ raise BadRequestError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 401:
+ raise UnauthorizedError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
if _response.status_code == 404:
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 500:
+ raise InternalServerError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -1633,64 +1413,116 @@ async def file_service_delete_file(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
- async def file_service_get_file_scan_status(
+ async def update_record(
self,
vault_id: str,
- table_name: str,
+ object_name: str,
id: str,
- column_name: str,
*,
+ record: typing.Optional[FieldRecords] = OMIT,
+ tokenization: typing.Optional[bool] = OMIT,
+ byot: typing.Optional[UpdateRecordRequestByot] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[V1GetFileScanStatusResponse]:
+ ) -> AsyncHttpResponse[UpdateRecordResponse]:
"""
- Returns the anti-virus scan status of a file.
+ Updates the specified record in a table.
When you update a field, include the entire contents you want the field to store. For JSON fields, include all nested fields and values. If a nested field isn't included, it's removed.
The time-to-live (TTL) for a transient field resets when the field value is updated.
Parameters
----------
vault_id : str
- ID of the vault.
- table_name : str
- Name of the table.
+ object_name : str
id : str
- `skyflow_id` of the record.
- column_name : str
- Name of the column that contains the file.
+ record : typing.Optional[FieldRecords]
+
+ tokenization : typing.Optional[bool]
+ If `true`, this operation returns tokens for fields with tokenization enabled.
+
+ byot : typing.Optional[UpdateRecordRequestByot]
+ Token insertion behavior.
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- AsyncHttpResponse[V1GetFileScanStatusResponse]
- A successful response.
+ AsyncHttpResponse[UpdateRecordResponse]
+ OK
"""
_response = await self._client_wrapper.httpx_client.request(
- f"v1/vaults/{jsonable_encoder(vault_id)}/{jsonable_encoder(table_name)}/{jsonable_encoder(id)}/files/{jsonable_encoder(column_name)}/scan-status",
- method="GET",
+ f"v1/vaults/{encode_path_param(vault_id)}/{encode_path_param(object_name)}/{encode_path_param(id)}",
+ method="PUT",
+ json={
+ "record": convert_and_respect_annotation_metadata(
+ object_=record, annotation=FieldRecords, direction="write"
+ ),
+ "tokenization": tokenization,
+ "byot": byot,
+ },
+ headers={
+ "content-type": "application/json",
+ },
request_options=request_options,
+ omit=OMIT,
)
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- V1GetFileScanStatusResponse,
+ UpdateRecordResponse,
parse_obj_as(
- type_=V1GetFileScanStatusResponse, # type: ignore
+ type_=UpdateRecordResponse, # type: ignore
object_=_response.json(),
),
)
return AsyncHttpResponse(response=_response, data=_data)
+ if _response.status_code == 400:
+ raise BadRequestError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 401:
+ raise UnauthorizedError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
if _response.status_code == 404:
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 500:
+ raise InternalServerError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -1698,72 +1530,48 @@ async def file_service_get_file_scan_status(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
- async def upload_file_v_2(
- self,
- vault_id: str,
- *,
- table_name: str,
- column_name: str,
- file: core.File,
- skyflow_id: typing.Optional[str] = OMIT,
- return_file_metadata: typing.Optional[bool] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[UploadFileV2Response]:
+ async def delete_record(
+ self, vault_id: str, object_name: str, id: str, *, request_options: typing.Optional[RequestOptions] = None
+ ) -> AsyncHttpResponse[DeleteRecordResponse]:
"""
- Uploads the specified file to a record. If an existing record isn't specified, creates a new record and uploads the file to that record.
+ Deletes the specified record from a table.
Note: This method doesn't delete transient field tokens. Transient field values are available until they expire based on the fields' time-to-live (TTL) setting.
Parameters
----------
vault_id : str
ID of the vault.
- table_name : str
- Name of the table to upload the file to.
-
- column_name : str
- Name of the column to upload the file to. The column must have a `file` data type.
-
- file : core.File
- See core.File for more documentation
-
- skyflow_id : typing.Optional[str]
- Skyflow ID of the record to upload the file to. If `skyflowID` isn't specified, a new record will be created.
+ object_name : str
+ Name of the table.
- return_file_metadata : typing.Optional[bool]
- If `true`, returns metadata about the uploaded file.
+ id : str
+ `skyflow_id` of the record to delete.
request_options : typing.Optional[RequestOptions]
Request-specific configuration.
Returns
-------
- AsyncHttpResponse[UploadFileV2Response]
- File uploaded successfully.
+ AsyncHttpResponse[DeleteRecordResponse]
+ OK
"""
_response = await self._client_wrapper.httpx_client.request(
- f"v2/vaults/{jsonable_encoder(vault_id)}/files/upload",
- method="POST",
- data={
- "tableName": table_name,
- "columnName": column_name,
- "skyflowID": skyflow_id,
- "returnFileMetadata": return_file_metadata,
- },
- files={
- "file": file,
- },
+ f"v1/vaults/{encode_path_param(vault_id)}/{encode_path_param(object_name)}/{encode_path_param(id)}",
+ method="DELETE",
request_options=request_options,
- omit=OMIT,
- force_multipart=True,
)
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- UploadFileV2Response,
+ DeleteRecordResponse,
parse_obj_as(
- type_=UploadFileV2Response, # type: ignore
+ type_=DeleteRecordResponse, # type: ignore
object_=_response.json(),
),
)
@@ -1772,9 +1580,9 @@ async def upload_file_v_2(
raise BadRequestError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -1783,9 +1591,9 @@ async def upload_file_v_2(
raise UnauthorizedError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -1794,9 +1602,9 @@ async def upload_file_v_2(
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -1815,4 +1623,8 @@ async def upload_file_v_2(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/skyvault/skyflow/generated/rest/records/types/__init__.py b/skyvault/skyflow/generated/rest/records/types/__init__.py
index 62f7c5c2..b5f1bff1 100644
--- a/skyvault/skyflow/generated/rest/records/types/__init__.py
+++ b/skyvault/skyflow/generated/rest/records/types/__init__.py
@@ -2,12 +2,49 @@
# isort: skip_file
-from .record_service_bulk_get_record_request_order_by import RecordServiceBulkGetRecordRequestOrderBy
-from .record_service_bulk_get_record_request_redaction import RecordServiceBulkGetRecordRequestRedaction
-from .record_service_get_record_request_redaction import RecordServiceGetRecordRequestRedaction
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .get_record_by_id_request_redaction import GetRecordByIdRequestRedaction
+ from .get_records_request_order_by import GetRecordsRequestOrderBy
+ from .get_records_request_redaction import GetRecordsRequestRedaction
+ from .insert_record_request_byot import InsertRecordRequestByot
+ from .update_record_request_byot import UpdateRecordRequestByot
+_dynamic_imports: typing.Dict[str, str] = {
+ "GetRecordByIdRequestRedaction": ".get_record_by_id_request_redaction",
+ "GetRecordsRequestOrderBy": ".get_records_request_order_by",
+ "GetRecordsRequestRedaction": ".get_records_request_redaction",
+ "InsertRecordRequestByot": ".insert_record_request_byot",
+ "UpdateRecordRequestByot": ".update_record_request_byot",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
__all__ = [
- "RecordServiceBulkGetRecordRequestOrderBy",
- "RecordServiceBulkGetRecordRequestRedaction",
- "RecordServiceGetRecordRequestRedaction",
+ "GetRecordByIdRequestRedaction",
+ "GetRecordsRequestOrderBy",
+ "GetRecordsRequestRedaction",
+ "InsertRecordRequestByot",
+ "UpdateRecordRequestByot",
]
diff --git a/skyvault/skyflow/generated/rest/records/types/get_record_by_id_request_redaction.py b/skyvault/skyflow/generated/rest/records/types/get_record_by_id_request_redaction.py
new file mode 100644
index 00000000..528d33a6
--- /dev/null
+++ b/skyvault/skyflow/generated/rest/records/types/get_record_by_id_request_redaction.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+GetRecordByIdRequestRedaction = typing.Union[typing.Literal["DEFAULT", "REDACTED", "MASKED", "PLAIN_TEXT"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/records/types/get_records_request_order_by.py b/skyvault/skyflow/generated/rest/records/types/get_records_request_order_by.py
new file mode 100644
index 00000000..5a6a1d78
--- /dev/null
+++ b/skyvault/skyflow/generated/rest/records/types/get_records_request_order_by.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+GetRecordsRequestOrderBy = typing.Union[typing.Literal["ASCENDING", "DESCENDING", "NONE"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/records/types/get_records_request_redaction.py b/skyvault/skyflow/generated/rest/records/types/get_records_request_redaction.py
new file mode 100644
index 00000000..a50cc679
--- /dev/null
+++ b/skyvault/skyflow/generated/rest/records/types/get_records_request_redaction.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+GetRecordsRequestRedaction = typing.Union[typing.Literal["DEFAULT", "REDACTED", "MASKED", "PLAIN_TEXT"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/records/types/insert_record_request_byot.py b/skyvault/skyflow/generated/rest/records/types/insert_record_request_byot.py
new file mode 100644
index 00000000..b8e9c55a
--- /dev/null
+++ b/skyvault/skyflow/generated/rest/records/types/insert_record_request_byot.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+InsertRecordRequestByot = typing.Union[typing.Literal["DISABLE", "ENABLE", "ENABLE_STRICT"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/records/types/record_service_bulk_get_record_request_order_by.py b/skyvault/skyflow/generated/rest/records/types/record_service_bulk_get_record_request_order_by.py
deleted file mode 100644
index 41f10c0b..00000000
--- a/skyvault/skyflow/generated/rest/records/types/record_service_bulk_get_record_request_order_by.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-RecordServiceBulkGetRecordRequestOrderBy = typing.Union[typing.Literal["ASCENDING", "DESCENDING", "NONE"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/records/types/record_service_bulk_get_record_request_redaction.py b/skyvault/skyflow/generated/rest/records/types/record_service_bulk_get_record_request_redaction.py
deleted file mode 100644
index 69bf6788..00000000
--- a/skyvault/skyflow/generated/rest/records/types/record_service_bulk_get_record_request_redaction.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-RecordServiceBulkGetRecordRequestRedaction = typing.Union[
- typing.Literal["DEFAULT", "REDACTED", "MASKED", "PLAIN_TEXT"], typing.Any
-]
diff --git a/skyvault/skyflow/generated/rest/records/types/update_record_request_byot.py b/skyvault/skyflow/generated/rest/records/types/update_record_request_byot.py
new file mode 100644
index 00000000..62ee48be
--- /dev/null
+++ b/skyvault/skyflow/generated/rest/records/types/update_record_request_byot.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+UpdateRecordRequestByot = typing.Union[typing.Literal["DISABLE", "ENABLE", "ENABLE_STRICT"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/strings/__init__.py b/skyvault/skyflow/generated/rest/strings/__init__.py
deleted file mode 100644
index 50bdd77e..00000000
--- a/skyvault/skyflow/generated/rest/strings/__init__.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-# isort: skip_file
-
-from .types import DeidentifyStringRequestEntityTypesItem
-
-__all__ = ["DeidentifyStringRequestEntityTypesItem"]
diff --git a/skyvault/skyflow/generated/rest/strings/client.py b/skyvault/skyflow/generated/rest/strings/client.py
deleted file mode 100644
index 88d8c2c2..00000000
--- a/skyvault/skyflow/generated/rest/strings/client.py
+++ /dev/null
@@ -1,296 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
-from ..core.request_options import RequestOptions
-from ..types.deidentify_string_response import DeidentifyStringResponse
-from ..types.format import Format
-from ..types.identify_response import IdentifyResponse
-from ..types.token_type_mapping import TokenTypeMapping
-from ..types.transformations import Transformations
-from .raw_client import AsyncRawStringsClient, RawStringsClient
-from .types.deidentify_string_request_entity_types_item import DeidentifyStringRequestEntityTypesItem
-
-# this is used as the default value for optional parameters
-OMIT = typing.cast(typing.Any, ...)
-
-
-class StringsClient:
- def __init__(self, *, client_wrapper: SyncClientWrapper):
- self._raw_client = RawStringsClient(client_wrapper=client_wrapper)
-
- @property
- def with_raw_response(self) -> RawStringsClient:
- """
- Retrieves a raw implementation of this client that returns raw responses.
-
- Returns
- -------
- RawStringsClient
- """
- return self._raw_client
-
- def deidentify_string(
- self,
- *,
- text: str,
- vault_id: str,
- entity_types: typing.Optional[typing.Sequence[DeidentifyStringRequestEntityTypesItem]] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> DeidentifyStringResponse:
- """
- De-identifies sensitive data from a string.
-
- Parameters
- ----------
- text : str
- Text to de-identify.
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyStringRequestEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- DeidentifyStringResponse
- OK
-
- Examples
- --------
- from skyflow import Skyflow
-
- client = Skyflow(
- token="YOUR_TOKEN",
- )
- client.strings.deidentify_string(
- text="text",
- vault_id="f4b3b3b3-3b3b-3b3b-3b3b-3b3b3b3b3b3b",
- )
- """
- _response = self._raw_client.deidentify_string(
- text=text,
- vault_id=vault_id,
- entity_types=entity_types,
- token_type=token_type,
- allow_regex=allow_regex,
- restrict_regex=restrict_regex,
- transformations=transformations,
- configuration_id=configuration_id,
- request_options=request_options,
- )
- return _response.data
-
- def reidentify_string(
- self,
- *,
- text: typing.Optional[str] = OMIT,
- vault_id: typing.Optional[str] = OMIT,
- format: typing.Optional[Format] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> IdentifyResponse:
- """
- Re-identifies tokens in a string.
-
- Parameters
- ----------
- text : typing.Optional[str]
- Text to reidentify.
-
- vault_id : typing.Optional[str]
- ID of the vault where the entities are stored.
-
- format : typing.Optional[Format]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- IdentifyResponse
- OK
-
- Examples
- --------
- from skyflow import Skyflow
-
- client = Skyflow(
- token="YOUR_TOKEN",
- )
- client.strings.reidentify_string()
- """
- _response = self._raw_client.reidentify_string(
- text=text, vault_id=vault_id, format=format, request_options=request_options
- )
- return _response.data
-
-
-class AsyncStringsClient:
- def __init__(self, *, client_wrapper: AsyncClientWrapper):
- self._raw_client = AsyncRawStringsClient(client_wrapper=client_wrapper)
-
- @property
- def with_raw_response(self) -> AsyncRawStringsClient:
- """
- Retrieves a raw implementation of this client that returns raw responses.
-
- Returns
- -------
- AsyncRawStringsClient
- """
- return self._raw_client
-
- async def deidentify_string(
- self,
- *,
- text: str,
- vault_id: str,
- entity_types: typing.Optional[typing.Sequence[DeidentifyStringRequestEntityTypesItem]] = OMIT,
- token_type: typing.Optional[TokenTypeMapping] = OMIT,
- allow_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- restrict_regex: typing.Optional[typing.Sequence[str]] = OMIT,
- transformations: typing.Optional[Transformations] = OMIT,
- configuration_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> DeidentifyStringResponse:
- """
- De-identifies sensitive data from a string.
-
- Parameters
- ----------
- text : str
- Text to de-identify.
-
- vault_id : str
- ID of a vault that you have Detect Invoker or Vault Owner permissions for.
-
- entity_types : typing.Optional[typing.Sequence[DeidentifyStringRequestEntityTypesItem]]
- Entities to detect and de-identify.
-
- token_type : typing.Optional[TokenTypeMapping]
-
- allow_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to display in plaintext. Entities appear in plaintext if an expression matches either the entirety of a detected entity or a substring of it. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext.
-
- restrict_regex : typing.Optional[typing.Sequence[str]]
- Regular expressions to replace with '[RESTRICTED]'. Expressions must match the entirety of a detected entity, not just a substring, for the entity to be restricted. Expressions don't match across entity boundaries. If a string or entity matches both `allow_regex` and `restrict_regex`, the entity is displayed in plaintext. If a string is detected as an entity and a `restrict_regex` pattern matches the entire detected entity, the entity is replaced with '[RESTRICTED]'. If a string is detected as an entity but a `restrict_regex` pattern only matches a substring of it, the `restrict_regex` pattern is ignored, and the entity is processed according to the specified tokenization and transformation settings.
-
- transformations : typing.Optional[Transformations]
-
- configuration_id : typing.Optional[str]
- ID of the Detect configuration to use for de-identification. Can't be specified with fields other than `vault_id`, `text`, and `file`.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- DeidentifyStringResponse
- OK
-
- Examples
- --------
- import asyncio
-
- from skyflow import AsyncSkyflow
-
- client = AsyncSkyflow(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.strings.deidentify_string(
- text="text",
- vault_id="f4b3b3b3-3b3b-3b3b-3b3b-3b3b3b3b3b3b",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._raw_client.deidentify_string(
- text=text,
- vault_id=vault_id,
- entity_types=entity_types,
- token_type=token_type,
- allow_regex=allow_regex,
- restrict_regex=restrict_regex,
- transformations=transformations,
- configuration_id=configuration_id,
- request_options=request_options,
- )
- return _response.data
-
- async def reidentify_string(
- self,
- *,
- text: typing.Optional[str] = OMIT,
- vault_id: typing.Optional[str] = OMIT,
- format: typing.Optional[Format] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> IdentifyResponse:
- """
- Re-identifies tokens in a string.
-
- Parameters
- ----------
- text : typing.Optional[str]
- Text to reidentify.
-
- vault_id : typing.Optional[str]
- ID of the vault where the entities are stored.
-
- format : typing.Optional[Format]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- IdentifyResponse
- OK
-
- Examples
- --------
- import asyncio
-
- from skyflow import AsyncSkyflow
-
- client = AsyncSkyflow(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.strings.reidentify_string()
-
-
- asyncio.run(main())
- """
- _response = await self._raw_client.reidentify_string(
- text=text, vault_id=vault_id, format=format, request_options=request_options
- )
- return _response.data
diff --git a/skyvault/skyflow/generated/rest/strings/types/__init__.py b/skyvault/skyflow/generated/rest/strings/types/__init__.py
deleted file mode 100644
index 592fae37..00000000
--- a/skyvault/skyflow/generated/rest/strings/types/__init__.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-# isort: skip_file
-
-from .deidentify_string_request_entity_types_item import DeidentifyStringRequestEntityTypesItem
-
-__all__ = ["DeidentifyStringRequestEntityTypesItem"]
diff --git a/skyvault/skyflow/generated/rest/strings/types/deidentify_string_request_entity_types_item.py b/skyvault/skyflow/generated/rest/strings/types/deidentify_string_request_entity_types_item.py
deleted file mode 100644
index bde5d084..00000000
--- a/skyvault/skyflow/generated/rest/strings/types/deidentify_string_request_entity_types_item.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-DeidentifyStringRequestEntityTypesItem = typing.Union[
- typing.Literal[
- "age",
- "bank_account",
- "credit_card",
- "credit_card_expiration",
- "cvv",
- "date",
- "date_interval",
- "dob",
- "driver_license",
- "email_address",
- "healthcare_number",
- "ip_address",
- "location",
- "name",
- "numerical_pii",
- "phone_number",
- "ssn",
- "url",
- "vehicle_id",
- "medical_code",
- "name_family",
- "name_given",
- "account_number",
- "event",
- "filename",
- "gender",
- "language",
- "location_address",
- "location_city",
- "location_coordinate",
- "location_country",
- "location_state",
- "location_zip",
- "marital_status",
- "money",
- "name_medical_professional",
- "occupation",
- "organization",
- "organization_medical_facility",
- "origin",
- "passport_number",
- "password",
- "physical_attribute",
- "political_affiliation",
- "religion",
- "time",
- "username",
- "zodiac_sign",
- "blood_type",
- "condition",
- "dose",
- "drug",
- "injury",
- "medical_process",
- "statistics",
- "routing_number",
- "corporate_action",
- "financial_metric",
- "product",
- "trend",
- "duration",
- "location_address_street",
- "all",
- "sexuality",
- "effect",
- "project",
- "organization_id",
- "day",
- "month",
- "year",
- ],
- typing.Any,
-]
diff --git a/skyvault/skyflow/generated/rest/tokens/client.py b/skyvault/skyflow/generated/rest/tokens/client.py
index a5c35064..25ba7dff 100644
--- a/skyvault/skyflow/generated/rest/tokens/client.py
+++ b/skyvault/skyflow/generated/rest/tokens/client.py
@@ -4,10 +4,10 @@
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.request_options import RequestOptions
-from ..types.v_1_detokenize_record_request import V1DetokenizeRecordRequest
-from ..types.v_1_detokenize_response import V1DetokenizeResponse
-from ..types.v_1_tokenize_record_request import V1TokenizeRecordRequest
-from ..types.v_1_tokenize_response import V1TokenizeResponse
+from ..types.detokenize_record_request import DetokenizeRecordRequest
+from ..types.detokenize_response import DetokenizeResponse
+from ..types.tokenize_record_request import TokenizeRecordRequest
+from ..types.tokenize_response import TokenizeResponse
from .raw_client import AsyncRawTokensClient, RawTokensClient
# this is used as the default value for optional parameters
@@ -29,24 +29,23 @@ def with_raw_response(self) -> RawTokensClient:
"""
return self._raw_client
- def record_service_detokenize(
+ def detokenize(
self,
vault_id: str,
*,
- detokenization_parameters: typing.Optional[typing.Sequence[V1DetokenizeRecordRequest]] = OMIT,
+ detokenization_parameters: typing.Sequence[DetokenizeRecordRequest],
download_url: typing.Optional[bool] = OMIT,
continue_on_error: typing.Optional[bool] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> V1DetokenizeResponse:
+ ) -> DetokenizeResponse:
"""
Returns records that correspond to the specified tokens.
Parameters
----------
vault_id : str
- ID of the vault.
- detokenization_parameters : typing.Optional[typing.Sequence[V1DetokenizeRecordRequest]]
+ detokenization_parameters : typing.Sequence[DetokenizeRecordRequest]
Detokenization details.
download_url : typing.Optional[bool]
@@ -60,32 +59,32 @@ def record_service_detokenize(
Returns
-------
- V1DetokenizeResponse
- A successful response.
+ DetokenizeResponse
+ OK
Examples
--------
- from skyflow import Skyflow, V1DetokenizeRecordRequest
+ from skyflow import DetokenizeRecordRequest, SkyflowAuth
- client = Skyflow(
+ client = SkyflowAuth(
token="YOUR_TOKEN",
)
- client.tokens.record_service_detokenize(
+ client.tokens.detokenize(
vault_id="vaultID",
detokenization_parameters=[
- V1DetokenizeRecordRequest(
- token="",
+ DetokenizeRecordRequest(
+ token="afbd1074-51c1-4a16-9eee-e2c0ecb52125",
redaction="PLAIN_TEXT",
),
- V1DetokenizeRecordRequest(
- token="",
+ DetokenizeRecordRequest(
+ token="05383487-fcae-42e5-a48e-5bd62a51af12",
redaction="DEFAULT",
),
],
download_url=False,
)
"""
- _response = self._raw_client.record_service_detokenize(
+ _response = self._raw_client.detokenize(
vault_id,
detokenization_parameters=detokenization_parameters,
download_url=download_url,
@@ -94,22 +93,22 @@ def record_service_detokenize(
)
return _response.data
- def record_service_tokenize(
+ def tokenize(
self,
vault_id: str,
*,
- tokenization_parameters: typing.Optional[typing.Sequence[V1TokenizeRecordRequest]] = OMIT,
+ tokenization_parameters: typing.Sequence[TokenizeRecordRequest],
request_options: typing.Optional[RequestOptions] = None,
- ) -> V1TokenizeResponse:
+ ) -> TokenizeResponse:
"""
- Returns tokens that correspond to the specified records. Only applicable for fields with deterministic tokenization.
Note: This endpoint doesn't insert records—it returns tokens for existing values. To insert records and tokenize that new record's values, see Insert Record and the tokenization parameter.
+ Returns tokens that correspond to the specified records. Only applicable for fields with deterministic tokenization.
Note: This endpoint doesn't insert records—it returns tokens for existing values. To insert records and return tokens for that new record's values, see Insert Records' `tokenization` parameter.
Parameters
----------
vault_id : str
ID of the vault.
- tokenization_parameters : typing.Optional[typing.Sequence[V1TokenizeRecordRequest]]
+ tokenization_parameters : typing.Sequence[TokenizeRecordRequest]
Tokenization details.
request_options : typing.Optional[RequestOptions]
@@ -117,21 +116,27 @@ def record_service_tokenize(
Returns
-------
- V1TokenizeResponse
- A successful response.
+ TokenizeResponse
+ OK
Examples
--------
- from skyflow import Skyflow
+ from skyflow import SkyflowAuth, TokenizeRecordRequest
- client = Skyflow(
+ client = SkyflowAuth(
token="YOUR_TOKEN",
)
- client.tokens.record_service_tokenize(
+ client.tokens.tokenize(
vault_id="vaultID",
+ tokenization_parameters=[
+ TokenizeRecordRequest(
+ value="26/02/2001",
+ column_group="persons_cg",
+ )
+ ],
)
"""
- _response = self._raw_client.record_service_tokenize(
+ _response = self._raw_client.tokenize(
vault_id, tokenization_parameters=tokenization_parameters, request_options=request_options
)
return _response.data
@@ -152,24 +157,23 @@ def with_raw_response(self) -> AsyncRawTokensClient:
"""
return self._raw_client
- async def record_service_detokenize(
+ async def detokenize(
self,
vault_id: str,
*,
- detokenization_parameters: typing.Optional[typing.Sequence[V1DetokenizeRecordRequest]] = OMIT,
+ detokenization_parameters: typing.Sequence[DetokenizeRecordRequest],
download_url: typing.Optional[bool] = OMIT,
continue_on_error: typing.Optional[bool] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> V1DetokenizeResponse:
+ ) -> DetokenizeResponse:
"""
Returns records that correspond to the specified tokens.
Parameters
----------
vault_id : str
- ID of the vault.
- detokenization_parameters : typing.Optional[typing.Sequence[V1DetokenizeRecordRequest]]
+ detokenization_parameters : typing.Sequence[DetokenizeRecordRequest]
Detokenization details.
download_url : typing.Optional[bool]
@@ -183,30 +187,30 @@ async def record_service_detokenize(
Returns
-------
- V1DetokenizeResponse
- A successful response.
+ DetokenizeResponse
+ OK
Examples
--------
import asyncio
- from skyflow import AsyncSkyflow, V1DetokenizeRecordRequest
+ from skyflow import AsyncSkyflowAuth, DetokenizeRecordRequest
- client = AsyncSkyflow(
+ client = AsyncSkyflowAuth(
token="YOUR_TOKEN",
)
async def main() -> None:
- await client.tokens.record_service_detokenize(
+ await client.tokens.detokenize(
vault_id="vaultID",
detokenization_parameters=[
- V1DetokenizeRecordRequest(
- token="",
+ DetokenizeRecordRequest(
+ token="afbd1074-51c1-4a16-9eee-e2c0ecb52125",
redaction="PLAIN_TEXT",
),
- V1DetokenizeRecordRequest(
- token="",
+ DetokenizeRecordRequest(
+ token="05383487-fcae-42e5-a48e-5bd62a51af12",
redaction="DEFAULT",
),
],
@@ -216,7 +220,7 @@ async def main() -> None:
asyncio.run(main())
"""
- _response = await self._raw_client.record_service_detokenize(
+ _response = await self._raw_client.detokenize(
vault_id,
detokenization_parameters=detokenization_parameters,
download_url=download_url,
@@ -225,22 +229,22 @@ async def main() -> None:
)
return _response.data
- async def record_service_tokenize(
+ async def tokenize(
self,
vault_id: str,
*,
- tokenization_parameters: typing.Optional[typing.Sequence[V1TokenizeRecordRequest]] = OMIT,
+ tokenization_parameters: typing.Sequence[TokenizeRecordRequest],
request_options: typing.Optional[RequestOptions] = None,
- ) -> V1TokenizeResponse:
+ ) -> TokenizeResponse:
"""
- Returns tokens that correspond to the specified records. Only applicable for fields with deterministic tokenization.
Note: This endpoint doesn't insert records—it returns tokens for existing values. To insert records and tokenize that new record's values, see Insert Record and the tokenization parameter.
+ Returns tokens that correspond to the specified records. Only applicable for fields with deterministic tokenization.
Note: This endpoint doesn't insert records—it returns tokens for existing values. To insert records and return tokens for that new record's values, see Insert Records' `tokenization` parameter.
Parameters
----------
vault_id : str
ID of the vault.
- tokenization_parameters : typing.Optional[typing.Sequence[V1TokenizeRecordRequest]]
+ tokenization_parameters : typing.Sequence[TokenizeRecordRequest]
Tokenization details.
request_options : typing.Optional[RequestOptions]
@@ -248,29 +252,35 @@ async def record_service_tokenize(
Returns
-------
- V1TokenizeResponse
- A successful response.
+ TokenizeResponse
+ OK
Examples
--------
import asyncio
- from skyflow import AsyncSkyflow
+ from skyflow import AsyncSkyflowAuth, TokenizeRecordRequest
- client = AsyncSkyflow(
+ client = AsyncSkyflowAuth(
token="YOUR_TOKEN",
)
async def main() -> None:
- await client.tokens.record_service_tokenize(
+ await client.tokens.tokenize(
vault_id="vaultID",
+ tokenization_parameters=[
+ TokenizeRecordRequest(
+ value="26/02/2001",
+ column_group="persons_cg",
+ )
+ ],
)
asyncio.run(main())
"""
- _response = await self._raw_client.record_service_tokenize(
+ _response = await self._raw_client.tokenize(
vault_id, tokenization_parameters=tokenization_parameters, request_options=request_options
)
return _response.data
diff --git a/skyvault/skyflow/generated/rest/tokens/raw_client.py b/skyvault/skyflow/generated/rest/tokens/raw_client.py
index 4741631d..afb67b70 100644
--- a/skyvault/skyflow/generated/rest/tokens/raw_client.py
+++ b/skyvault/skyflow/generated/rest/tokens/raw_client.py
@@ -6,15 +6,21 @@
from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.http_response import AsyncHttpResponse, HttpResponse
-from ..core.jsonable_encoder import jsonable_encoder
+from ..core.jsonable_encoder import encode_path_param
+from ..core.parse_error import ParsingError
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
from ..core.serialization import convert_and_respect_annotation_metadata
+from ..errors.bad_request_error import BadRequestError
+from ..errors.internal_server_error import InternalServerError
from ..errors.not_found_error import NotFoundError
-from ..types.v_1_detokenize_record_request import V1DetokenizeRecordRequest
-from ..types.v_1_detokenize_response import V1DetokenizeResponse
-from ..types.v_1_tokenize_record_request import V1TokenizeRecordRequest
-from ..types.v_1_tokenize_response import V1TokenizeResponse
+from ..errors.unauthorized_error import UnauthorizedError
+from ..types.detokenize_record_request import DetokenizeRecordRequest
+from ..types.detokenize_response import DetokenizeResponse
+from ..types.error_response import ErrorResponse
+from ..types.tokenize_record_request import TokenizeRecordRequest
+from ..types.tokenize_response import TokenizeResponse
+from pydantic import ValidationError
# this is used as the default value for optional parameters
OMIT = typing.cast(typing.Any, ...)
@@ -24,24 +30,23 @@ class RawTokensClient:
def __init__(self, *, client_wrapper: SyncClientWrapper):
self._client_wrapper = client_wrapper
- def record_service_detokenize(
+ def detokenize(
self,
vault_id: str,
*,
- detokenization_parameters: typing.Optional[typing.Sequence[V1DetokenizeRecordRequest]] = OMIT,
+ detokenization_parameters: typing.Sequence[DetokenizeRecordRequest],
download_url: typing.Optional[bool] = OMIT,
continue_on_error: typing.Optional[bool] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[V1DetokenizeResponse]:
+ ) -> HttpResponse[DetokenizeResponse]:
"""
Returns records that correspond to the specified tokens.
Parameters
----------
vault_id : str
- ID of the vault.
- detokenization_parameters : typing.Optional[typing.Sequence[V1DetokenizeRecordRequest]]
+ detokenization_parameters : typing.Sequence[DetokenizeRecordRequest]
Detokenization details.
download_url : typing.Optional[bool]
@@ -55,16 +60,16 @@ def record_service_detokenize(
Returns
-------
- HttpResponse[V1DetokenizeResponse]
- A successful response.
+ HttpResponse[DetokenizeResponse]
+ OK
"""
_response = self._client_wrapper.httpx_client.request(
- f"v1/vaults/{jsonable_encoder(vault_id)}/detokenize",
+ f"v1/vaults/{encode_path_param(vault_id)}/detokenize",
method="POST",
json={
"detokenizationParameters": convert_and_respect_annotation_metadata(
object_=detokenization_parameters,
- annotation=typing.Sequence[V1DetokenizeRecordRequest],
+ annotation=typing.Sequence[DetokenizeRecordRequest],
direction="write",
),
"downloadURL": download_url,
@@ -79,20 +84,53 @@ def record_service_detokenize(
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- V1DetokenizeResponse,
+ DetokenizeResponse,
parse_obj_as(
- type_=V1DetokenizeResponse, # type: ignore
+ type_=DetokenizeResponse, # type: ignore
object_=_response.json(),
),
)
return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 400:
+ raise BadRequestError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 401:
+ raise UnauthorizedError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
if _response.status_code == 404:
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 500:
+ raise InternalServerError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -100,24 +138,28 @@ def record_service_detokenize(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
- def record_service_tokenize(
+ def tokenize(
self,
vault_id: str,
*,
- tokenization_parameters: typing.Optional[typing.Sequence[V1TokenizeRecordRequest]] = OMIT,
+ tokenization_parameters: typing.Sequence[TokenizeRecordRequest],
request_options: typing.Optional[RequestOptions] = None,
- ) -> HttpResponse[V1TokenizeResponse]:
+ ) -> HttpResponse[TokenizeResponse]:
"""
- Returns tokens that correspond to the specified records. Only applicable for fields with deterministic tokenization.
Note: This endpoint doesn't insert records—it returns tokens for existing values. To insert records and tokenize that new record's values, see Insert Record and the tokenization parameter.
+ Returns tokens that correspond to the specified records. Only applicable for fields with deterministic tokenization.
Note: This endpoint doesn't insert records—it returns tokens for existing values. To insert records and return tokens for that new record's values, see Insert Records' `tokenization` parameter.
Parameters
----------
vault_id : str
ID of the vault.
- tokenization_parameters : typing.Optional[typing.Sequence[V1TokenizeRecordRequest]]
+ tokenization_parameters : typing.Sequence[TokenizeRecordRequest]
Tokenization details.
request_options : typing.Optional[RequestOptions]
@@ -125,16 +167,16 @@ def record_service_tokenize(
Returns
-------
- HttpResponse[V1TokenizeResponse]
- A successful response.
+ HttpResponse[TokenizeResponse]
+ OK
"""
_response = self._client_wrapper.httpx_client.request(
- f"v1/vaults/{jsonable_encoder(vault_id)}/tokenize",
+ f"v1/vaults/{encode_path_param(vault_id)}/tokenize",
method="POST",
json={
"tokenizationParameters": convert_and_respect_annotation_metadata(
object_=tokenization_parameters,
- annotation=typing.Sequence[V1TokenizeRecordRequest],
+ annotation=typing.Sequence[TokenizeRecordRequest],
direction="write",
),
},
@@ -147,20 +189,53 @@ def record_service_tokenize(
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- V1TokenizeResponse,
+ TokenizeResponse,
parse_obj_as(
- type_=V1TokenizeResponse, # type: ignore
+ type_=TokenizeResponse, # type: ignore
object_=_response.json(),
),
)
return HttpResponse(response=_response, data=_data)
+ if _response.status_code == 400:
+ raise BadRequestError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 401:
+ raise UnauthorizedError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
if _response.status_code == 404:
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 500:
+ raise InternalServerError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -168,6 +243,10 @@ def record_service_tokenize(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
@@ -175,24 +254,23 @@ class AsyncRawTokensClient:
def __init__(self, *, client_wrapper: AsyncClientWrapper):
self._client_wrapper = client_wrapper
- async def record_service_detokenize(
+ async def detokenize(
self,
vault_id: str,
*,
- detokenization_parameters: typing.Optional[typing.Sequence[V1DetokenizeRecordRequest]] = OMIT,
+ detokenization_parameters: typing.Sequence[DetokenizeRecordRequest],
download_url: typing.Optional[bool] = OMIT,
continue_on_error: typing.Optional[bool] = OMIT,
request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[V1DetokenizeResponse]:
+ ) -> AsyncHttpResponse[DetokenizeResponse]:
"""
Returns records that correspond to the specified tokens.
Parameters
----------
vault_id : str
- ID of the vault.
- detokenization_parameters : typing.Optional[typing.Sequence[V1DetokenizeRecordRequest]]
+ detokenization_parameters : typing.Sequence[DetokenizeRecordRequest]
Detokenization details.
download_url : typing.Optional[bool]
@@ -206,16 +284,16 @@ async def record_service_detokenize(
Returns
-------
- AsyncHttpResponse[V1DetokenizeResponse]
- A successful response.
+ AsyncHttpResponse[DetokenizeResponse]
+ OK
"""
_response = await self._client_wrapper.httpx_client.request(
- f"v1/vaults/{jsonable_encoder(vault_id)}/detokenize",
+ f"v1/vaults/{encode_path_param(vault_id)}/detokenize",
method="POST",
json={
"detokenizationParameters": convert_and_respect_annotation_metadata(
object_=detokenization_parameters,
- annotation=typing.Sequence[V1DetokenizeRecordRequest],
+ annotation=typing.Sequence[DetokenizeRecordRequest],
direction="write",
),
"downloadURL": download_url,
@@ -230,20 +308,53 @@ async def record_service_detokenize(
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- V1DetokenizeResponse,
+ DetokenizeResponse,
parse_obj_as(
- type_=V1DetokenizeResponse, # type: ignore
+ type_=DetokenizeResponse, # type: ignore
object_=_response.json(),
),
)
return AsyncHttpResponse(response=_response, data=_data)
+ if _response.status_code == 400:
+ raise BadRequestError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 401:
+ raise UnauthorizedError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
if _response.status_code == 404:
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 500:
+ raise InternalServerError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -251,24 +362,28 @@ async def record_service_detokenize(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
- async def record_service_tokenize(
+ async def tokenize(
self,
vault_id: str,
*,
- tokenization_parameters: typing.Optional[typing.Sequence[V1TokenizeRecordRequest]] = OMIT,
+ tokenization_parameters: typing.Sequence[TokenizeRecordRequest],
request_options: typing.Optional[RequestOptions] = None,
- ) -> AsyncHttpResponse[V1TokenizeResponse]:
+ ) -> AsyncHttpResponse[TokenizeResponse]:
"""
- Returns tokens that correspond to the specified records. Only applicable for fields with deterministic tokenization.
Note: This endpoint doesn't insert records—it returns tokens for existing values. To insert records and tokenize that new record's values, see Insert Record and the tokenization parameter.
+ Returns tokens that correspond to the specified records. Only applicable for fields with deterministic tokenization.
Note: This endpoint doesn't insert records—it returns tokens for existing values. To insert records and return tokens for that new record's values, see Insert Records' `tokenization` parameter.
Parameters
----------
vault_id : str
ID of the vault.
- tokenization_parameters : typing.Optional[typing.Sequence[V1TokenizeRecordRequest]]
+ tokenization_parameters : typing.Sequence[TokenizeRecordRequest]
Tokenization details.
request_options : typing.Optional[RequestOptions]
@@ -276,16 +391,16 @@ async def record_service_tokenize(
Returns
-------
- AsyncHttpResponse[V1TokenizeResponse]
- A successful response.
+ AsyncHttpResponse[TokenizeResponse]
+ OK
"""
_response = await self._client_wrapper.httpx_client.request(
- f"v1/vaults/{jsonable_encoder(vault_id)}/tokenize",
+ f"v1/vaults/{encode_path_param(vault_id)}/tokenize",
method="POST",
json={
"tokenizationParameters": convert_and_respect_annotation_metadata(
object_=tokenization_parameters,
- annotation=typing.Sequence[V1TokenizeRecordRequest],
+ annotation=typing.Sequence[TokenizeRecordRequest],
direction="write",
),
},
@@ -298,20 +413,53 @@ async def record_service_tokenize(
try:
if 200 <= _response.status_code < 300:
_data = typing.cast(
- V1TokenizeResponse,
+ TokenizeResponse,
parse_obj_as(
- type_=V1TokenizeResponse, # type: ignore
+ type_=TokenizeResponse, # type: ignore
object_=_response.json(),
),
)
return AsyncHttpResponse(response=_response, data=_data)
+ if _response.status_code == 400:
+ raise BadRequestError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 401:
+ raise UnauthorizedError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
if _response.status_code == 404:
raise NotFoundError(
headers=dict(_response.headers),
body=typing.cast(
- typing.Optional[typing.Any],
+ ErrorResponse,
+ parse_obj_as(
+ type_=ErrorResponse, # type: ignore
+ object_=_response.json(),
+ ),
+ ),
+ )
+ if _response.status_code == 500:
+ raise InternalServerError(
+ headers=dict(_response.headers),
+ body=typing.cast(
+ ErrorResponse,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=ErrorResponse, # type: ignore
object_=_response.json(),
),
),
@@ -319,4 +467,8 @@ async def record_service_tokenize(
_response_json = _response.json()
except JSONDecodeError:
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
+ except ValidationError as e:
+ raise ParsingError(
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.json(), cause=e
+ )
raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
diff --git a/skyvault/skyflow/generated/rest/types/__init__.py b/skyvault/skyflow/generated/rest/types/__init__.py
index 11929765..ec36b212 100644
--- a/skyvault/skyflow/generated/rest/types/__init__.py
+++ b/skyvault/skyflow/generated/rest/types/__init__.py
@@ -2,202 +2,112 @@
# isort: skip_file
-from .audit_event_audit_resource_type import AuditEventAuditResourceType
-from .audit_event_context import AuditEventContext
-from .audit_event_data import AuditEventData
-from .audit_event_http_info import AuditEventHttpInfo
-from .batch_record_method import BatchRecordMethod
-from .context_access_type import ContextAccessType
-from .context_auth_mode import ContextAuthMode
-from .deidentified_file_output import DeidentifiedFileOutput
-from .deidentified_file_output_processed_file_extension import DeidentifiedFileOutputProcessedFileExtension
-from .deidentified_file_output_processed_file_type import DeidentifiedFileOutputProcessedFileType
-from .deidentify_file_response import DeidentifyFileResponse
-from .deidentify_string_response import DeidentifyStringResponse
-from .detect_guardrails_response import DetectGuardrailsResponse
-from .detect_guardrails_response_validation import DetectGuardrailsResponseValidation
-from .detect_runs_response import DetectRunsResponse
-from .detect_runs_response_output_type import DetectRunsResponseOutputType
-from .detect_runs_response_status import DetectRunsResponseStatus
-from .detokenize_record_response_value_type import DetokenizeRecordResponseValueType
-from .error_response import ErrorResponse
-from .error_response_error import ErrorResponseError
-from .file_data import FileData
-from .file_data_data_format import FileDataDataFormat
-from .file_data_deidentify_audio import FileDataDeidentifyAudio
-from .file_data_deidentify_audio_data_format import FileDataDeidentifyAudioDataFormat
-from .file_data_deidentify_document import FileDataDeidentifyDocument
-from .file_data_deidentify_document_data_format import FileDataDeidentifyDocumentDataFormat
-from .file_data_deidentify_image import FileDataDeidentifyImage
-from .file_data_deidentify_image_data_format import FileDataDeidentifyImageDataFormat
-from .file_data_deidentify_pdf import FileDataDeidentifyPdf
-from .file_data_deidentify_presentation import FileDataDeidentifyPresentation
-from .file_data_deidentify_presentation_data_format import FileDataDeidentifyPresentationDataFormat
-from .file_data_deidentify_spreadsheet import FileDataDeidentifySpreadsheet
-from .file_data_deidentify_spreadsheet_data_format import FileDataDeidentifySpreadsheetDataFormat
-from .file_data_deidentify_structured_text import FileDataDeidentifyStructuredText
-from .file_data_deidentify_structured_text_data_format import FileDataDeidentifyStructuredTextDataFormat
-from .file_data_deidentify_text import FileDataDeidentifyText
-from .file_data_reidentify_file import FileDataReidentifyFile
-from .file_data_reidentify_file_data_format import FileDataReidentifyFileDataFormat
-from .format import Format
-from .format_masked_item import FormatMaskedItem
-from .format_plaintext_item import FormatPlaintextItem
-from .format_redacted_item import FormatRedactedItem
-from .googlerpc_status import GooglerpcStatus
-from .http_code import HttpCode
-from .identify_response import IdentifyResponse
-from .locations import Locations
-from .protobuf_any import ProtobufAny
-from .redaction_enum_redaction import RedactionEnumRedaction
-from .reidentified_file_output import ReidentifiedFileOutput
-from .reidentified_file_output_processed_file_extension import ReidentifiedFileOutputProcessedFileExtension
-from .reidentify_file_response import ReidentifyFileResponse
-from .reidentify_file_response_output_type import ReidentifyFileResponseOutputType
-from .reidentify_file_response_status import ReidentifyFileResponseStatus
-from .request_action_type import RequestActionType
-from .resource_id import ResourceId
-from .shift_dates import ShiftDates
-from .shift_dates_entity_types_item import ShiftDatesEntityTypesItem
-from .string_response_entities import StringResponseEntities
-from .token_type_mapping import TokenTypeMapping
-from .token_type_mapping_default import TokenTypeMappingDefault
-from .token_type_mapping_entity_only_item import TokenTypeMappingEntityOnlyItem
-from .token_type_mapping_entity_unq_counter_item import TokenTypeMappingEntityUnqCounterItem
-from .token_type_mapping_vault_token_item import TokenTypeMappingVaultTokenItem
-from .transformations import Transformations
-from .upload_file_v_2_response import UploadFileV2Response
-from .uuid_ import Uuid
-from .v_1_audit_after_options import V1AuditAfterOptions
-from .v_1_audit_event_response import V1AuditEventResponse
-from .v_1_audit_response import V1AuditResponse
-from .v_1_audit_response_event import V1AuditResponseEvent
-from .v_1_audit_response_event_request import V1AuditResponseEventRequest
-from .v_1_batch_operation_response import V1BatchOperationResponse
-from .v_1_batch_record import V1BatchRecord
-from .v_1_bin_list_response import V1BinListResponse
-from .v_1_bulk_delete_record_response import V1BulkDeleteRecordResponse
-from .v_1_bulk_get_record_response import V1BulkGetRecordResponse
-from .v_1_byot import V1Byot
-from .v_1_card import V1Card
-from .v_1_delete_file_response import V1DeleteFileResponse
-from .v_1_delete_record_response import V1DeleteRecordResponse
-from .v_1_detokenize_record_request import V1DetokenizeRecordRequest
-from .v_1_detokenize_record_response import V1DetokenizeRecordResponse
-from .v_1_detokenize_response import V1DetokenizeResponse
-from .v_1_field_records import V1FieldRecords
-from .v_1_file_av_scan_status import V1FileAvScanStatus
-from .v_1_get_auth_token_response import V1GetAuthTokenResponse
-from .v_1_get_file_scan_status_response import V1GetFileScanStatusResponse
-from .v_1_get_query_response import V1GetQueryResponse
-from .v_1_insert_record_response import V1InsertRecordResponse
-from .v_1_member_type import V1MemberType
-from .v_1_record_meta_properties import V1RecordMetaProperties
-from .v_1_tokenize_record_request import V1TokenizeRecordRequest
-from .v_1_tokenize_record_response import V1TokenizeRecordResponse
-from .v_1_tokenize_response import V1TokenizeResponse
-from .v_1_update_record_response import V1UpdateRecordResponse
-from .v_1_vault_field_mapping import V1VaultFieldMapping
-from .v_1_vault_schema_config import V1VaultSchemaConfig
-from .word_character_count import WordCharacterCount
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .batch_operation_response import BatchOperationResponse
+ from .batch_record import BatchRecord
+ from .batch_record_method import BatchRecordMethod
+ from .batch_record_redaction import BatchRecordRedaction
+ from .bulk_delete_record_response import BulkDeleteRecordResponse
+ from .bulk_get_record_response import BulkGetRecordResponse
+ from .delete_record_response import DeleteRecordResponse
+ from .detokenize_record_request import DetokenizeRecordRequest
+ from .detokenize_record_request_redaction import DetokenizeRecordRequestRedaction
+ from .detokenize_record_response import DetokenizeRecordResponse
+ from .detokenize_record_response_value_type import DetokenizeRecordResponseValueType
+ from .detokenize_response import DetokenizeResponse
+ from .error_response import ErrorResponse
+ from .error_response_error import ErrorResponseError
+ from .field_records import FieldRecords
+ from .file_metadata import FileMetadata
+ from .get_field_records import GetFieldRecords
+ from .get_query_response import GetQueryResponse
+ from .http_code import HttpCode
+ from .insert_record_response import InsertRecordResponse
+ from .record_meta_properties import RecordMetaProperties
+ from .tokenize_record_request import TokenizeRecordRequest
+ from .tokenize_record_response import TokenizeRecordResponse
+ from .tokenize_response import TokenizeResponse
+ from .update_record_response import UpdateRecordResponse
+ from .upload_file_response_v2 import UploadFileResponseV2
+_dynamic_imports: typing.Dict[str, str] = {
+ "BatchOperationResponse": ".batch_operation_response",
+ "BatchRecord": ".batch_record",
+ "BatchRecordMethod": ".batch_record_method",
+ "BatchRecordRedaction": ".batch_record_redaction",
+ "BulkDeleteRecordResponse": ".bulk_delete_record_response",
+ "BulkGetRecordResponse": ".bulk_get_record_response",
+ "DeleteRecordResponse": ".delete_record_response",
+ "DetokenizeRecordRequest": ".detokenize_record_request",
+ "DetokenizeRecordRequestRedaction": ".detokenize_record_request_redaction",
+ "DetokenizeRecordResponse": ".detokenize_record_response",
+ "DetokenizeRecordResponseValueType": ".detokenize_record_response_value_type",
+ "DetokenizeResponse": ".detokenize_response",
+ "ErrorResponse": ".error_response",
+ "ErrorResponseError": ".error_response_error",
+ "FieldRecords": ".field_records",
+ "FileMetadata": ".file_metadata",
+ "GetFieldRecords": ".get_field_records",
+ "GetQueryResponse": ".get_query_response",
+ "HttpCode": ".http_code",
+ "InsertRecordResponse": ".insert_record_response",
+ "RecordMetaProperties": ".record_meta_properties",
+ "TokenizeRecordRequest": ".tokenize_record_request",
+ "TokenizeRecordResponse": ".tokenize_record_response",
+ "TokenizeResponse": ".tokenize_response",
+ "UpdateRecordResponse": ".update_record_response",
+ "UploadFileResponseV2": ".upload_file_response_v2",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
__all__ = [
- "AuditEventAuditResourceType",
- "AuditEventContext",
- "AuditEventData",
- "AuditEventHttpInfo",
+ "BatchOperationResponse",
+ "BatchRecord",
"BatchRecordMethod",
- "ContextAccessType",
- "ContextAuthMode",
- "DeidentifiedFileOutput",
- "DeidentifiedFileOutputProcessedFileExtension",
- "DeidentifiedFileOutputProcessedFileType",
- "DeidentifyFileResponse",
- "DeidentifyStringResponse",
- "DetectGuardrailsResponse",
- "DetectGuardrailsResponseValidation",
- "DetectRunsResponse",
- "DetectRunsResponseOutputType",
- "DetectRunsResponseStatus",
+ "BatchRecordRedaction",
+ "BulkDeleteRecordResponse",
+ "BulkGetRecordResponse",
+ "DeleteRecordResponse",
+ "DetokenizeRecordRequest",
+ "DetokenizeRecordRequestRedaction",
+ "DetokenizeRecordResponse",
"DetokenizeRecordResponseValueType",
+ "DetokenizeResponse",
"ErrorResponse",
"ErrorResponseError",
- "FileData",
- "FileDataDataFormat",
- "FileDataDeidentifyAudio",
- "FileDataDeidentifyAudioDataFormat",
- "FileDataDeidentifyDocument",
- "FileDataDeidentifyDocumentDataFormat",
- "FileDataDeidentifyImage",
- "FileDataDeidentifyImageDataFormat",
- "FileDataDeidentifyPdf",
- "FileDataDeidentifyPresentation",
- "FileDataDeidentifyPresentationDataFormat",
- "FileDataDeidentifySpreadsheet",
- "FileDataDeidentifySpreadsheetDataFormat",
- "FileDataDeidentifyStructuredText",
- "FileDataDeidentifyStructuredTextDataFormat",
- "FileDataDeidentifyText",
- "FileDataReidentifyFile",
- "FileDataReidentifyFileDataFormat",
- "Format",
- "FormatMaskedItem",
- "FormatPlaintextItem",
- "FormatRedactedItem",
- "GooglerpcStatus",
+ "FieldRecords",
+ "FileMetadata",
+ "GetFieldRecords",
+ "GetQueryResponse",
"HttpCode",
- "IdentifyResponse",
- "Locations",
- "ProtobufAny",
- "RedactionEnumRedaction",
- "ReidentifiedFileOutput",
- "ReidentifiedFileOutputProcessedFileExtension",
- "ReidentifyFileResponse",
- "ReidentifyFileResponseOutputType",
- "ReidentifyFileResponseStatus",
- "RequestActionType",
- "ResourceId",
- "ShiftDates",
- "ShiftDatesEntityTypesItem",
- "StringResponseEntities",
- "TokenTypeMapping",
- "TokenTypeMappingDefault",
- "TokenTypeMappingEntityOnlyItem",
- "TokenTypeMappingEntityUnqCounterItem",
- "TokenTypeMappingVaultTokenItem",
- "Transformations",
- "UploadFileV2Response",
- "Uuid",
- "V1AuditAfterOptions",
- "V1AuditEventResponse",
- "V1AuditResponse",
- "V1AuditResponseEvent",
- "V1AuditResponseEventRequest",
- "V1BatchOperationResponse",
- "V1BatchRecord",
- "V1BinListResponse",
- "V1BulkDeleteRecordResponse",
- "V1BulkGetRecordResponse",
- "V1Byot",
- "V1Card",
- "V1DeleteFileResponse",
- "V1DeleteRecordResponse",
- "V1DetokenizeRecordRequest",
- "V1DetokenizeRecordResponse",
- "V1DetokenizeResponse",
- "V1FieldRecords",
- "V1FileAvScanStatus",
- "V1GetAuthTokenResponse",
- "V1GetFileScanStatusResponse",
- "V1GetQueryResponse",
- "V1InsertRecordResponse",
- "V1MemberType",
- "V1RecordMetaProperties",
- "V1TokenizeRecordRequest",
- "V1TokenizeRecordResponse",
- "V1TokenizeResponse",
- "V1UpdateRecordResponse",
- "V1VaultFieldMapping",
- "V1VaultSchemaConfig",
- "WordCharacterCount",
+ "InsertRecordResponse",
+ "RecordMetaProperties",
+ "TokenizeRecordRequest",
+ "TokenizeRecordResponse",
+ "TokenizeResponse",
+ "UpdateRecordResponse",
+ "UploadFileResponseV2",
]
diff --git a/skyvault/skyflow/generated/rest/types/audit_event_audit_resource_type.py b/skyvault/skyflow/generated/rest/types/audit_event_audit_resource_type.py
deleted file mode 100644
index b6c6aa0c..00000000
--- a/skyvault/skyflow/generated/rest/types/audit_event_audit_resource_type.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-AuditEventAuditResourceType = typing.Union[
- typing.Literal[
- "NONE_API",
- "ACCOUNT",
- "AUDIT",
- "BASE_DATA_TYPE",
- "FIELD_TEMPLATE",
- "FILE",
- "KEY",
- "POLICY",
- "PROTO_PARSE",
- "RECORD",
- "ROLE",
- "RULE",
- "SECRET",
- "SERVICE_ACCOUNT",
- "TOKEN",
- "USER",
- "VAULT",
- "VAULT_TEMPLATE",
- "WORKSPACE",
- "TABLE",
- "POLICY_TEMPLATE",
- "MEMBER",
- "TAG",
- "CONNECTION",
- "MIGRATION",
- "SCHEDULED_JOB",
- "JOB",
- "COLUMN_NAME",
- "NETWORK_TOKEN",
- "SUBSCRIPTION",
- ],
- typing.Any,
-]
diff --git a/skyvault/skyflow/generated/rest/types/audit_event_context.py b/skyvault/skyflow/generated/rest/types/audit_event_context.py
deleted file mode 100644
index 92287d5a..00000000
--- a/skyvault/skyflow/generated/rest/types/audit_event_context.py
+++ /dev/null
@@ -1,90 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-import typing_extensions
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from ..core.serialization import FieldMetadata
-from .context_access_type import ContextAccessType
-from .context_auth_mode import ContextAuthMode
-from .v_1_member_type import V1MemberType
-
-
-class AuditEventContext(UniversalBaseModel):
- """
- Context for an audit event.
- """
-
- change_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="changeID")] = pydantic.Field(
- default=None
- )
- """
- ID for the audit event.
- """
-
- request_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="requestID")] = pydantic.Field(
- default=None
- )
- """
- ID for the request that caused the event.
- """
-
- trace_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="traceID")] = pydantic.Field(
- default=None
- )
- """
- ID for the request set by the service that received the request.
- """
-
- session_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="sessionID")] = pydantic.Field(
- default=None
- )
- """
- ID for the session in which the request was sent.
- """
-
- actor: typing.Optional[str] = pydantic.Field(default=None)
- """
- Member who sent the request. Depending on `actorType`, this may be a user ID or a service account ID.
- """
-
- actor_type: typing_extensions.Annotated[typing.Optional[V1MemberType], FieldMetadata(alias="actorType")] = None
- access_type: typing_extensions.Annotated[typing.Optional[ContextAccessType], FieldMetadata(alias="accessType")] = (
- None
- )
- ip_address: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="ipAddress")] = pydantic.Field(
- default=None
- )
- """
- IP Address of the client that made the request.
- """
-
- origin: typing.Optional[str] = pydantic.Field(default=None)
- """
- HTTP Origin request header (including scheme, hostname, and port) of the request.
- """
-
- auth_mode: typing_extensions.Annotated[typing.Optional[ContextAuthMode], FieldMetadata(alias="authMode")] = None
- jwt_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="jwtID")] = pydantic.Field(
- default=None
- )
- """
- ID of the JWT token.
- """
-
- bearer_token_context_id: typing_extensions.Annotated[
- typing.Optional[str], FieldMetadata(alias="bearerTokenContextID")
- ] = pydantic.Field(default=None)
- """
- Embedded User Context.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/v_1_batch_operation_response.py b/skyvault/skyflow/generated/rest/types/batch_operation_response.py
similarity index 77%
rename from skyvault/skyflow/generated/rest/types/v_1_batch_operation_response.py
rename to skyvault/skyflow/generated/rest/types/batch_operation_response.py
index 9e7144a6..cc02d5de 100644
--- a/skyvault/skyflow/generated/rest/types/v_1_batch_operation_response.py
+++ b/skyvault/skyflow/generated/rest/types/batch_operation_response.py
@@ -8,17 +8,17 @@
from ..core.serialization import FieldMetadata
-class V1BatchOperationResponse(UniversalBaseModel):
- vault_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="vaultID")] = pydantic.Field(
- default=None
- )
+class BatchOperationResponse(UniversalBaseModel):
+ vault_id: typing_extensions.Annotated[
+ typing.Optional[str],
+ FieldMetadata(alias="vaultID"),
+ pydantic.Field(alias="vaultID", description="ID of the vault."),
+ ] = None
"""
ID of the vault.
"""
- responses: typing.Optional[typing.List[typing.Dict[str, typing.Optional[typing.Any]]]] = pydantic.Field(
- default=None
- )
+ responses: typing.Optional[typing.List[typing.Dict[str, typing.Any]]] = pydantic.Field(default=None)
"""
Responses in the same order as in the request. Responses have the same payload structure as their corresponding APIs:
- `POST` returns an Insert Records response.
- `PUT` returns an Update Record response.
- `GET` returns a Get Record response.
- `DELETE` returns a Delete Record response.
"""
diff --git a/skyvault/skyflow/generated/rest/types/batch_record.py b/skyvault/skyflow/generated/rest/types/batch_record.py
new file mode 100644
index 00000000..4b9eb378
--- /dev/null
+++ b/skyvault/skyflow/generated/rest/types/batch_record.py
@@ -0,0 +1,105 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+import typing_extensions
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from ..core.serialization import FieldMetadata
+from .batch_record_method import BatchRecordMethod
+from .batch_record_redaction import BatchRecordRedaction
+
+
+class BatchRecord(UniversalBaseModel):
+ fields: typing.Dict[str, typing.Any] = pydantic.Field()
+ """
+ Field and value key pairs. For example, `{'field_1':'value_1', 'field_2':'value_2'}`. Only valid when `method` is `POST` or `PUT`.
+ """
+
+ table_name: typing_extensions.Annotated[
+ str,
+ FieldMetadata(alias="tableName"),
+ pydantic.Field(alias="tableName", description="Name of the table to perform the operation on."),
+ ]
+ """
+ Name of the table to perform the operation on.
+ """
+
+ method: BatchRecordMethod = pydantic.Field()
+ """
+ Method of the operation.
+ """
+
+ batch_id: typing_extensions.Annotated[
+ typing.Optional[str],
+ FieldMetadata(alias="batchID"),
+ pydantic.Field(
+ alias="batchID",
+ description="ID to group operations by. Operations in the same group are executed sequentially.",
+ ),
+ ] = None
+ """
+ ID to group operations by. Operations in the same group are executed sequentially.
+ """
+
+ redaction: typing.Optional[BatchRecordRedaction] = pydantic.Field(default=None)
+ """
+ Redaction level to enforce for the returned record. Subject to policies assigned to the API caller.
+ """
+
+ tokenization: typing.Optional[bool] = pydantic.Field(default=None)
+ """
+ If `true`, this operation returns tokens for fields with tokenization enabled. Only applicable if `skyflow_id` values are specified.
+ """
+
+ id: typing_extensions.Annotated[
+ typing.Optional[str],
+ FieldMetadata(alias="ID"),
+ pydantic.Field(
+ alias="ID",
+ description="`skyflow_id` for the record. Only valid when `method` is `GET`, `DELETE`, or `PUT`.",
+ ),
+ ] = None
+ """
+ `skyflow_id` for the record. Only valid when `method` is `GET`, `DELETE`, or `PUT`.
+ """
+
+ download_url: typing_extensions.Annotated[
+ typing.Optional[bool],
+ FieldMetadata(alias="downloadURL"),
+ pydantic.Field(
+ alias="downloadURL",
+ description="If `true`, returns download URLs for fields with a file data type. URLs are valid for 15 minutes. If virus scanning is enabled, only returns if the file is clean.",
+ ),
+ ] = None
+ """
+ If `true`, returns download URLs for fields with a file data type. URLs are valid for 15 minutes. If virus scanning is enabled, only returns if the file is clean.
+ """
+
+ upsert: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Column that stores primary keys for upsert operations. The column must be marked as unique in the vault schema. Only valid when `method` is `POST`.
+ """
+
+ tokens: typing.Optional[typing.Dict[str, typing.Any]] = pydantic.Field(default=None)
+ """
+ Fields and tokens for the record. For example, `{'field_1':'token_1', 'field_2':'token_2'}`.
+ """
+
+ return_file_metadata: typing_extensions.Annotated[
+ typing.Optional[bool],
+ FieldMetadata(alias="returnFileMetadata"),
+ pydantic.Field(alias="returnFileMetadata", description="If `true`, returns metadata for files."),
+ ] = None
+ """
+ If `true`, returns metadata for files.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/batch_record_method.py b/skyvault/skyflow/generated/rest/types/batch_record_method.py
index e1882ba5..776a335b 100644
--- a/skyvault/skyflow/generated/rest/types/batch_record_method.py
+++ b/skyvault/skyflow/generated/rest/types/batch_record_method.py
@@ -2,4 +2,4 @@
import typing
-BatchRecordMethod = typing.Union[typing.Literal["NONE", "POST", "PUT", "GET", "DELETE"], typing.Any]
+BatchRecordMethod = typing.Union[typing.Literal["POST", "PUT", "GET", "DELETE"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/types/batch_record_redaction.py b/skyvault/skyflow/generated/rest/types/batch_record_redaction.py
new file mode 100644
index 00000000..e74adea1
--- /dev/null
+++ b/skyvault/skyflow/generated/rest/types/batch_record_redaction.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+BatchRecordRedaction = typing.Union[typing.Literal["DEFAULT", "REDACTED", "MASKED", "PLAIN_TEXT"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/types/v_1_bulk_delete_record_response.py b/skyvault/skyflow/generated/rest/types/bulk_delete_record_response.py
similarity index 68%
rename from skyvault/skyflow/generated/rest/types/v_1_bulk_delete_record_response.py
rename to skyvault/skyflow/generated/rest/types/bulk_delete_record_response.py
index bae86dc3..5b3c7a11 100644
--- a/skyvault/skyflow/generated/rest/types/v_1_bulk_delete_record_response.py
+++ b/skyvault/skyflow/generated/rest/types/bulk_delete_record_response.py
@@ -8,10 +8,14 @@
from ..core.serialization import FieldMetadata
-class V1BulkDeleteRecordResponse(UniversalBaseModel):
+class BulkDeleteRecordResponse(UniversalBaseModel):
record_id_response: typing_extensions.Annotated[
- typing.Optional[typing.List[str]], FieldMetadata(alias="RecordIDResponse")
- ] = pydantic.Field(default=None)
+ typing.Optional[typing.List[str]],
+ FieldMetadata(alias="RecordIDResponse"),
+ pydantic.Field(
+ alias="RecordIDResponse", description="IDs for the deleted records, or `*` if all records were deleted."
+ ),
+ ] = None
"""
IDs for the deleted records, or `*` if all records were deleted.
"""
diff --git a/skyvault/skyflow/generated/rest/types/v_1_bulk_get_record_response.py b/skyvault/skyflow/generated/rest/types/bulk_get_record_response.py
similarity index 73%
rename from skyvault/skyflow/generated/rest/types/v_1_bulk_get_record_response.py
rename to skyvault/skyflow/generated/rest/types/bulk_get_record_response.py
index 385a8132..1e73689d 100644
--- a/skyvault/skyflow/generated/rest/types/v_1_bulk_get_record_response.py
+++ b/skyvault/skyflow/generated/rest/types/bulk_get_record_response.py
@@ -4,11 +4,11 @@
import pydantic
from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from .v_1_field_records import V1FieldRecords
+from .get_field_records import GetFieldRecords
-class V1BulkGetRecordResponse(UniversalBaseModel):
- records: typing.Optional[typing.List[V1FieldRecords]] = pydantic.Field(default=None)
+class BulkGetRecordResponse(UniversalBaseModel):
+ records: typing.Optional[typing.List[GetFieldRecords]] = pydantic.Field(default=None)
"""
The specified records.
"""
diff --git a/skyvault/skyflow/generated/rest/types/context_access_type.py b/skyvault/skyflow/generated/rest/types/context_access_type.py
deleted file mode 100644
index 056a10f4..00000000
--- a/skyvault/skyflow/generated/rest/types/context_access_type.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-ContextAccessType = typing.Union[typing.Literal["ACCESS_NONE", "API", "SQL"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/types/context_auth_mode.py b/skyvault/skyflow/generated/rest/types/context_auth_mode.py
deleted file mode 100644
index ad630625..00000000
--- a/skyvault/skyflow/generated/rest/types/context_auth_mode.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-ContextAuthMode = typing.Union[typing.Literal["AUTH_NONE", "OKTA_JWT", "SERVICE_ACCOUNT_JWT", "PAT_JWT"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/types/deidentified_file_output.py b/skyvault/skyflow/generated/rest/types/deidentified_file_output.py
deleted file mode 100644
index 387f57f2..00000000
--- a/skyvault/skyflow/generated/rest/types/deidentified_file_output.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-import typing_extensions
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from ..core.serialization import FieldMetadata
-from .deidentified_file_output_processed_file_extension import DeidentifiedFileOutputProcessedFileExtension
-from .deidentified_file_output_processed_file_type import DeidentifiedFileOutputProcessedFileType
-
-
-class DeidentifiedFileOutput(UniversalBaseModel):
- """
- Details of output files. Files are specified as Base64-encoded data.
- """
-
- processed_file: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="processedFile")] = (
- pydantic.Field(default=None)
- )
- """
- File content in Base64 format.
- """
-
- processed_file_type: typing_extensions.Annotated[
- typing.Optional[DeidentifiedFileOutputProcessedFileType], FieldMetadata(alias="processedFileType")
- ] = pydantic.Field(default=None)
- """
- Type of the processed file.
- """
-
- processed_file_extension: typing_extensions.Annotated[
- typing.Optional[DeidentifiedFileOutputProcessedFileExtension], FieldMetadata(alias="processedFileExtension")
- ] = pydantic.Field(default=None)
- """
- Extension of the processed file.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/deidentified_file_output_processed_file_extension.py b/skyvault/skyflow/generated/rest/types/deidentified_file_output_processed_file_extension.py
deleted file mode 100644
index dc3a8519..00000000
--- a/skyvault/skyflow/generated/rest/types/deidentified_file_output_processed_file_extension.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-DeidentifiedFileOutputProcessedFileExtension = typing.Union[
- typing.Literal[
- "mp3",
- "wav",
- "pdf",
- "txt",
- "csv",
- "json",
- "jpg",
- "jpeg",
- "tif",
- "tiff",
- "png",
- "bmp",
- "xls",
- "xlsx",
- "doc",
- "docx",
- "ppt",
- "pptx",
- "xml",
- "dcm",
- ],
- typing.Any,
-]
diff --git a/skyvault/skyflow/generated/rest/types/deidentified_file_output_processed_file_type.py b/skyvault/skyflow/generated/rest/types/deidentified_file_output_processed_file_type.py
deleted file mode 100644
index ca5aadfc..00000000
--- a/skyvault/skyflow/generated/rest/types/deidentified_file_output_processed_file_type.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-DeidentifiedFileOutputProcessedFileType = typing.Union[
- typing.Literal[
- "redacted_audio",
- "redacted_image",
- "redacted_transcription",
- "redacted_file",
- "redacted_text",
- "entities",
- "redacted_transcription_diarize_json",
- ],
- typing.Any,
-]
diff --git a/skyvault/skyflow/generated/rest/types/deidentify_string_response.py b/skyvault/skyflow/generated/rest/types/deidentify_string_response.py
deleted file mode 100644
index 4655f80b..00000000
--- a/skyvault/skyflow/generated/rest/types/deidentify_string_response.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from .string_response_entities import StringResponseEntities
-
-
-class DeidentifyStringResponse(UniversalBaseModel):
- """
- Response to deidentify a string.
- """
-
- processed_text: typing.Optional[str] = pydantic.Field(default=None)
- """
- De-identified text.
- """
-
- entities: typing.Optional[typing.List[StringResponseEntities]] = pydantic.Field(default=None)
- """
- Detected entities.
- """
-
- word_count: typing.Optional[int] = pydantic.Field(default=None)
- """
- Number of words from the input text.
- """
-
- character_count: typing.Optional[int] = pydantic.Field(default=None)
- """
- Number of characters from the input text.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/v_1_delete_record_response.py b/skyvault/skyflow/generated/rest/types/delete_record_response.py
similarity index 93%
rename from skyvault/skyflow/generated/rest/types/v_1_delete_record_response.py
rename to skyvault/skyflow/generated/rest/types/delete_record_response.py
index 4007abca..8c57e6f4 100644
--- a/skyvault/skyflow/generated/rest/types/v_1_delete_record_response.py
+++ b/skyvault/skyflow/generated/rest/types/delete_record_response.py
@@ -6,7 +6,7 @@
from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-class V1DeleteRecordResponse(UniversalBaseModel):
+class DeleteRecordResponse(UniversalBaseModel):
skyflow_id: typing.Optional[str] = pydantic.Field(default=None)
"""
ID of the deleted record.
diff --git a/skyvault/skyflow/generated/rest/types/detect_guardrails_response_validation.py b/skyvault/skyflow/generated/rest/types/detect_guardrails_response_validation.py
deleted file mode 100644
index 5a59ddb0..00000000
--- a/skyvault/skyflow/generated/rest/types/detect_guardrails_response_validation.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-DetectGuardrailsResponseValidation = typing.Union[typing.Literal["failed", "passed"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/types/detect_runs_response.py b/skyvault/skyflow/generated/rest/types/detect_runs_response.py
deleted file mode 100644
index e49cca0a..00000000
--- a/skyvault/skyflow/generated/rest/types/detect_runs_response.py
+++ /dev/null
@@ -1,72 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-import typing_extensions
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from ..core.serialization import FieldMetadata
-from .deidentified_file_output import DeidentifiedFileOutput
-from .detect_runs_response_output_type import DetectRunsResponseOutputType
-from .detect_runs_response_status import DetectRunsResponseStatus
-from .word_character_count import WordCharacterCount
-
-
-class DetectRunsResponse(UniversalBaseModel):
- """
- Response to get the status of a file deidentification request.
- """
-
- status: typing.Optional[DetectRunsResponseStatus] = pydantic.Field(default=None)
- """
- Status of the operation.
- """
-
- output_type: typing_extensions.Annotated[
- typing.Optional[DetectRunsResponseOutputType], FieldMetadata(alias="outputType")
- ] = pydantic.Field(default=None)
- """
- Format of the output file.
- """
-
- output: typing.Optional[typing.List[DeidentifiedFileOutput]] = pydantic.Field(default=None)
- """
- Details of output files. Files are specified as Base64-encoded data.
- """
-
- message: typing.Optional[str] = pydantic.Field(default=None)
- """
- Status details about the Detect run.
- """
-
- size: typing.Optional[float] = pydantic.Field(default=None)
- """
- Size of the processed file in kilobytes (KB).
- """
-
- word_character_count: typing_extensions.Annotated[
- typing.Optional[WordCharacterCount], FieldMetadata(alias="wordCharacterCount")
- ] = None
- duration: typing.Optional[float] = pydantic.Field(default=None)
- """
- Duration of the processed audio in seconds.
- """
-
- pages: typing.Optional[int] = pydantic.Field(default=None)
- """
- Number of pages in the processed PDF.
- """
-
- slides: typing.Optional[int] = pydantic.Field(default=None)
- """
- Number of slides in the processed presentation.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/detect_runs_response_output_type.py b/skyvault/skyflow/generated/rest/types/detect_runs_response_output_type.py
deleted file mode 100644
index a24870c1..00000000
--- a/skyvault/skyflow/generated/rest/types/detect_runs_response_output_type.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-DetectRunsResponseOutputType = typing.Union[typing.Literal["UNKNOWN", "BASE64"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/types/detect_runs_response_status.py b/skyvault/skyflow/generated/rest/types/detect_runs_response_status.py
deleted file mode 100644
index 979454c6..00000000
--- a/skyvault/skyflow/generated/rest/types/detect_runs_response_status.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-DetectRunsResponseStatus = typing.Union[typing.Literal["UNKNOWN", "FAILED", "SUCCESS", "IN_PROGRESS"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/types/v_1_detokenize_record_request.py b/skyvault/skyflow/generated/rest/types/detokenize_record_request.py
similarity index 58%
rename from skyvault/skyflow/generated/rest/types/v_1_detokenize_record_request.py
rename to skyvault/skyflow/generated/rest/types/detokenize_record_request.py
index ef75d346..e9a21bb7 100644
--- a/skyvault/skyflow/generated/rest/types/v_1_detokenize_record_request.py
+++ b/skyvault/skyflow/generated/rest/types/detokenize_record_request.py
@@ -4,16 +4,19 @@
import pydantic
from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from .redaction_enum_redaction import RedactionEnumRedaction
+from .detokenize_record_request_redaction import DetokenizeRecordRequestRedaction
-class V1DetokenizeRecordRequest(UniversalBaseModel):
- token: typing.Optional[str] = pydantic.Field(default=None)
+class DetokenizeRecordRequest(UniversalBaseModel):
+ token: str = pydantic.Field()
"""
Token that identifies the record to detokenize.
"""
- redaction: typing.Optional[RedactionEnumRedaction] = None
+ redaction: typing.Optional[DetokenizeRecordRequestRedaction] = pydantic.Field(default=None)
+ """
+ Redaction level to enforce for the returned record. Subject to policies assigned to the API caller.
+ """
if IS_PYDANTIC_V2:
model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
diff --git a/skyvault/skyflow/generated/rest/records/types/record_service_get_record_request_redaction.py b/skyvault/skyflow/generated/rest/types/detokenize_record_request_redaction.py
similarity index 74%
rename from skyvault/skyflow/generated/rest/records/types/record_service_get_record_request_redaction.py
rename to skyvault/skyflow/generated/rest/types/detokenize_record_request_redaction.py
index d7de8c1a..c14fb750 100644
--- a/skyvault/skyflow/generated/rest/records/types/record_service_get_record_request_redaction.py
+++ b/skyvault/skyflow/generated/rest/types/detokenize_record_request_redaction.py
@@ -2,6 +2,6 @@
import typing
-RecordServiceGetRecordRequestRedaction = typing.Union[
+DetokenizeRecordRequestRedaction = typing.Union[
typing.Literal["DEFAULT", "REDACTED", "MASKED", "PLAIN_TEXT"], typing.Any
]
diff --git a/skyvault/skyflow/generated/rest/types/v_1_detokenize_record_response.py b/skyvault/skyflow/generated/rest/types/detokenize_record_response.py
similarity index 78%
rename from skyvault/skyflow/generated/rest/types/v_1_detokenize_record_response.py
rename to skyvault/skyflow/generated/rest/types/detokenize_record_response.py
index 4cce821c..b06f1dc3 100644
--- a/skyvault/skyflow/generated/rest/types/v_1_detokenize_record_response.py
+++ b/skyvault/skyflow/generated/rest/types/detokenize_record_response.py
@@ -9,15 +9,21 @@
from .detokenize_record_response_value_type import DetokenizeRecordResponseValueType
-class V1DetokenizeRecordResponse(UniversalBaseModel):
+class DetokenizeRecordResponse(UniversalBaseModel):
token: typing.Optional[str] = pydantic.Field(default=None)
"""
Token of the record.
"""
value_type: typing_extensions.Annotated[
- typing.Optional[DetokenizeRecordResponseValueType], FieldMetadata(alias="valueType")
+ typing.Optional[DetokenizeRecordResponseValueType],
+ FieldMetadata(alias="valueType"),
+ pydantic.Field(alias="valueType", description="Data type of the `value`."),
] = None
+ """
+ Data type of the `value`.
+ """
+
value: typing.Optional[str] = pydantic.Field(default=None)
"""
Data corresponding to the token.
diff --git a/skyvault/skyflow/generated/rest/types/detokenize_record_response_value_type.py b/skyvault/skyflow/generated/rest/types/detokenize_record_response_value_type.py
index 3703064a..7273f154 100644
--- a/skyvault/skyflow/generated/rest/types/detokenize_record_response_value_type.py
+++ b/skyvault/skyflow/generated/rest/types/detokenize_record_response_value_type.py
@@ -3,5 +3,5 @@
import typing
DetokenizeRecordResponseValueType = typing.Union[
- typing.Literal["NONE", "STRING", "INTEGER", "FLOAT", "BOOL", "DATETIME", "JSON", "ARRAY", "DATE"], typing.Any
+ typing.Literal["STRING", "INTEGER", "FLOAT", "BOOL", "DATETIME", "JSON", "ARRAY", "DATE", "TIME"], typing.Any
]
diff --git a/skyvault/skyflow/generated/rest/types/v_1_detokenize_response.py b/skyvault/skyflow/generated/rest/types/detokenize_response.py
similarity index 70%
rename from skyvault/skyflow/generated/rest/types/v_1_detokenize_response.py
rename to skyvault/skyflow/generated/rest/types/detokenize_response.py
index 34759550..566763a4 100644
--- a/skyvault/skyflow/generated/rest/types/v_1_detokenize_response.py
+++ b/skyvault/skyflow/generated/rest/types/detokenize_response.py
@@ -4,11 +4,11 @@
import pydantic
from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from .v_1_detokenize_record_response import V1DetokenizeRecordResponse
+from .detokenize_record_response import DetokenizeRecordResponse
-class V1DetokenizeResponse(UniversalBaseModel):
- records: typing.Optional[typing.List[V1DetokenizeRecordResponse]] = pydantic.Field(default=None)
+class DetokenizeResponse(UniversalBaseModel):
+ records: typing.Optional[typing.List[DetokenizeRecordResponse]] = pydantic.Field(default=None)
"""
Records corresponding to the specified tokens.
"""
diff --git a/skyvault/skyflow/generated/rest/types/error_response_error.py b/skyvault/skyflow/generated/rest/types/error_response_error.py
index efe080d3..13d9fc11 100644
--- a/skyvault/skyflow/generated/rest/types/error_response_error.py
+++ b/skyvault/skyflow/generated/rest/types/error_response_error.py
@@ -16,7 +16,7 @@ class ErrorResponseError(UniversalBaseModel):
http_code: HttpCode
http_status: str
message: str
- details: typing.Optional[typing.List[typing.Dict[str, typing.Optional[typing.Any]]]] = None
+ details: typing.Optional[typing.List[typing.Dict[str, typing.Any]]] = None
if IS_PYDANTIC_V2:
model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
diff --git a/skyvault/skyflow/generated/rest/types/v_1_field_records.py b/skyvault/skyflow/generated/rest/types/field_records.py
similarity index 74%
rename from skyvault/skyflow/generated/rest/types/v_1_field_records.py
rename to skyvault/skyflow/generated/rest/types/field_records.py
index fbedfcfe..855de031 100644
--- a/skyvault/skyflow/generated/rest/types/v_1_field_records.py
+++ b/skyvault/skyflow/generated/rest/types/field_records.py
@@ -6,17 +6,17 @@
from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-class V1FieldRecords(UniversalBaseModel):
+class FieldRecords(UniversalBaseModel):
"""
Record values and tokens.
"""
- fields: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None)
+ fields: typing.Optional[typing.Dict[str, typing.Any]] = pydantic.Field(default=None)
"""
Fields and values for the record. For example, `{'field_1':'value_1', 'field_2':'value_2'}`.
"""
- tokens: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None)
+ tokens: typing.Optional[typing.Dict[str, typing.Any]] = pydantic.Field(default=None)
"""
Fields and tokens for the record. For example, `{'field_1':'token_1', 'field_2':'token_2'}`.
"""
diff --git a/skyvault/skyflow/generated/rest/types/file_data.py b/skyvault/skyflow/generated/rest/types/file_data.py
deleted file mode 100644
index 846837e0..00000000
--- a/skyvault/skyflow/generated/rest/types/file_data.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-import typing_extensions
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from ..core.serialization import FieldMetadata
-from .file_data_data_format import FileDataDataFormat
-
-
-class FileData(UniversalBaseModel):
- """
- File to process. Files are specified as Base64-encoded data.
- """
-
- base_64: typing_extensions.Annotated[str, FieldMetadata(alias="base64")] = pydantic.Field()
- """
- Base64-encoded data of the file.
- """
-
- data_format: FileDataDataFormat = pydantic.Field()
- """
- Format of the file.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/file_data_deidentify_audio.py b/skyvault/skyflow/generated/rest/types/file_data_deidentify_audio.py
deleted file mode 100644
index 8973b22a..00000000
--- a/skyvault/skyflow/generated/rest/types/file_data_deidentify_audio.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-import typing_extensions
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from ..core.serialization import FieldMetadata
-from .file_data_deidentify_audio_data_format import FileDataDeidentifyAudioDataFormat
-
-
-class FileDataDeidentifyAudio(UniversalBaseModel):
- """
- File to process. Files are specified as Base64-encoded data.
- """
-
- base_64: typing_extensions.Annotated[str, FieldMetadata(alias="base64")] = pydantic.Field()
- """
- Base64-encoded data of the file.
- """
-
- data_format: FileDataDeidentifyAudioDataFormat = pydantic.Field()
- """
- Format of the file.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/file_data_deidentify_audio_data_format.py b/skyvault/skyflow/generated/rest/types/file_data_deidentify_audio_data_format.py
deleted file mode 100644
index 85f163c2..00000000
--- a/skyvault/skyflow/generated/rest/types/file_data_deidentify_audio_data_format.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-FileDataDeidentifyAudioDataFormat = typing.Union[typing.Literal["mp3", "wav"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/types/file_data_deidentify_document.py b/skyvault/skyflow/generated/rest/types/file_data_deidentify_document.py
deleted file mode 100644
index ef9b61f2..00000000
--- a/skyvault/skyflow/generated/rest/types/file_data_deidentify_document.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-import typing_extensions
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from ..core.serialization import FieldMetadata
-from .file_data_deidentify_document_data_format import FileDataDeidentifyDocumentDataFormat
-
-
-class FileDataDeidentifyDocument(UniversalBaseModel):
- """
- File to process. Files are specified as Base64-encoded data.
- """
-
- base_64: typing_extensions.Annotated[str, FieldMetadata(alias="base64")] = pydantic.Field()
- """
- Base64-encoded data of the file.
- """
-
- data_format: FileDataDeidentifyDocumentDataFormat = pydantic.Field()
- """
- Format of the file.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/file_data_deidentify_document_data_format.py b/skyvault/skyflow/generated/rest/types/file_data_deidentify_document_data_format.py
deleted file mode 100644
index beaf1ffc..00000000
--- a/skyvault/skyflow/generated/rest/types/file_data_deidentify_document_data_format.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-FileDataDeidentifyDocumentDataFormat = typing.Union[typing.Literal["pdf", "doc", "docx"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/types/file_data_deidentify_image.py b/skyvault/skyflow/generated/rest/types/file_data_deidentify_image.py
deleted file mode 100644
index c1f76298..00000000
--- a/skyvault/skyflow/generated/rest/types/file_data_deidentify_image.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-import typing_extensions
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from ..core.serialization import FieldMetadata
-from .file_data_deidentify_image_data_format import FileDataDeidentifyImageDataFormat
-
-
-class FileDataDeidentifyImage(UniversalBaseModel):
- """
- File to process. Files are specified as Base64-encoded data.
- """
-
- base_64: typing_extensions.Annotated[str, FieldMetadata(alias="base64")] = pydantic.Field()
- """
- Base64-encoded data of the file.
- """
-
- data_format: FileDataDeidentifyImageDataFormat = pydantic.Field()
- """
- Format of the file.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/file_data_deidentify_image_data_format.py b/skyvault/skyflow/generated/rest/types/file_data_deidentify_image_data_format.py
deleted file mode 100644
index 97dab89e..00000000
--- a/skyvault/skyflow/generated/rest/types/file_data_deidentify_image_data_format.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-FileDataDeidentifyImageDataFormat = typing.Union[typing.Literal["jpg", "jpeg", "tif", "tiff", "png", "bmp"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/types/file_data_deidentify_presentation.py b/skyvault/skyflow/generated/rest/types/file_data_deidentify_presentation.py
deleted file mode 100644
index 17fa004e..00000000
--- a/skyvault/skyflow/generated/rest/types/file_data_deidentify_presentation.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-import typing_extensions
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from ..core.serialization import FieldMetadata
-from .file_data_deidentify_presentation_data_format import FileDataDeidentifyPresentationDataFormat
-
-
-class FileDataDeidentifyPresentation(UniversalBaseModel):
- """
- File to process. Files are specified as Base64-encoded data.
- """
-
- base_64: typing_extensions.Annotated[str, FieldMetadata(alias="base64")] = pydantic.Field()
- """
- Base64-encoded data of the file.
- """
-
- data_format: FileDataDeidentifyPresentationDataFormat = pydantic.Field()
- """
- Format of the file.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/file_data_deidentify_presentation_data_format.py b/skyvault/skyflow/generated/rest/types/file_data_deidentify_presentation_data_format.py
deleted file mode 100644
index d811746d..00000000
--- a/skyvault/skyflow/generated/rest/types/file_data_deidentify_presentation_data_format.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-FileDataDeidentifyPresentationDataFormat = typing.Union[typing.Literal["ppt", "pptx"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/types/file_data_deidentify_spreadsheet.py b/skyvault/skyflow/generated/rest/types/file_data_deidentify_spreadsheet.py
deleted file mode 100644
index 17ead2f1..00000000
--- a/skyvault/skyflow/generated/rest/types/file_data_deidentify_spreadsheet.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-import typing_extensions
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from ..core.serialization import FieldMetadata
-from .file_data_deidentify_spreadsheet_data_format import FileDataDeidentifySpreadsheetDataFormat
-
-
-class FileDataDeidentifySpreadsheet(UniversalBaseModel):
- """
- File to process. Files are specified as Base64-encoded data.
- """
-
- base_64: typing_extensions.Annotated[str, FieldMetadata(alias="base64")] = pydantic.Field()
- """
- Base64-encoded data of the file.
- """
-
- data_format: FileDataDeidentifySpreadsheetDataFormat = pydantic.Field()
- """
- Format of the file.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/file_data_deidentify_spreadsheet_data_format.py b/skyvault/skyflow/generated/rest/types/file_data_deidentify_spreadsheet_data_format.py
deleted file mode 100644
index f48a11aa..00000000
--- a/skyvault/skyflow/generated/rest/types/file_data_deidentify_spreadsheet_data_format.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-FileDataDeidentifySpreadsheetDataFormat = typing.Union[typing.Literal["csv", "xls", "xlsx"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/types/file_data_deidentify_structured_text.py b/skyvault/skyflow/generated/rest/types/file_data_deidentify_structured_text.py
deleted file mode 100644
index a78a11ab..00000000
--- a/skyvault/skyflow/generated/rest/types/file_data_deidentify_structured_text.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-import typing_extensions
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from ..core.serialization import FieldMetadata
-from .file_data_deidentify_structured_text_data_format import FileDataDeidentifyStructuredTextDataFormat
-
-
-class FileDataDeidentifyStructuredText(UniversalBaseModel):
- """
- File to process. Files are specified as Base64-encoded data.
- """
-
- base_64: typing_extensions.Annotated[str, FieldMetadata(alias="base64")] = pydantic.Field()
- """
- Base64-encoded data of the file.
- """
-
- data_format: FileDataDeidentifyStructuredTextDataFormat = pydantic.Field()
- """
- Format of the file.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/file_data_deidentify_structured_text_data_format.py b/skyvault/skyflow/generated/rest/types/file_data_deidentify_structured_text_data_format.py
deleted file mode 100644
index 267b17a6..00000000
--- a/skyvault/skyflow/generated/rest/types/file_data_deidentify_structured_text_data_format.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-FileDataDeidentifyStructuredTextDataFormat = typing.Union[typing.Literal["json", "xml"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/types/file_data_deidentify_text.py b/skyvault/skyflow/generated/rest/types/file_data_deidentify_text.py
deleted file mode 100644
index c8637361..00000000
--- a/skyvault/skyflow/generated/rest/types/file_data_deidentify_text.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-import typing_extensions
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from ..core.serialization import FieldMetadata
-
-
-class FileDataDeidentifyText(UniversalBaseModel):
- """
- File to process. Files are specified as Base64-encoded data.
- """
-
- base_64: typing_extensions.Annotated[str, FieldMetadata(alias="base64")] = pydantic.Field()
- """
- Base64-encoded data of the file.
- """
-
- data_format: typing.Literal["txt"] = pydantic.Field(default="txt")
- """
- Format of the file.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/file_data_reidentify_file.py b/skyvault/skyflow/generated/rest/types/file_data_reidentify_file.py
deleted file mode 100644
index d691bcc0..00000000
--- a/skyvault/skyflow/generated/rest/types/file_data_reidentify_file.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-import typing_extensions
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from ..core.serialization import FieldMetadata
-from .file_data_reidentify_file_data_format import FileDataReidentifyFileDataFormat
-
-
-class FileDataReidentifyFile(UniversalBaseModel):
- """
- File to process. Files are specified as Base64-encoded data.
- """
-
- base_64: typing_extensions.Annotated[str, FieldMetadata(alias="base64")] = pydantic.Field()
- """
- Base64-encoded data of the file.
- """
-
- data_format: FileDataReidentifyFileDataFormat = pydantic.Field()
- """
- Format of the file.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/file_data_reidentify_file_data_format.py b/skyvault/skyflow/generated/rest/types/file_data_reidentify_file_data_format.py
deleted file mode 100644
index d0cc44ba..00000000
--- a/skyvault/skyflow/generated/rest/types/file_data_reidentify_file_data_format.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-FileDataReidentifyFileDataFormat = typing.Union[
- typing.Literal["txt", "csv", "json", "xls", "xlsx", "doc", "docx", "xml"], typing.Any
-]
diff --git a/skyvault/skyflow/generated/rest/types/file_metadata.py b/skyvault/skyflow/generated/rest/types/file_metadata.py
new file mode 100644
index 00000000..6174b9f6
--- /dev/null
+++ b/skyvault/skyflow/generated/rest/types/file_metadata.py
@@ -0,0 +1,53 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+import typing_extensions
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from ..core.serialization import FieldMetadata
+
+
+class FileMetadata(UniversalBaseModel):
+ """
+ Metadata about the file, including its name, size, and type.
+ """
+
+ file_name: typing_extensions.Annotated[
+ typing.Optional[str],
+ FieldMetadata(alias="fileName"),
+ pydantic.Field(alias="fileName", description="Name of the file, including the extension if provided."),
+ ] = None
+ """
+ Name of the file, including the extension if provided.
+ """
+
+ file_size_kb: typing_extensions.Annotated[
+ typing.Optional[int],
+ FieldMetadata(alias="fileSizeKB"),
+ pydantic.Field(
+ alias="fileSizeKB",
+ description="Size of the file in kilobytes (KB), rounded up from bytes to the nearest KB.",
+ ),
+ ] = None
+ """
+ Size of the file in kilobytes (KB), rounded up from bytes to the nearest KB.
+ """
+
+ file_type: typing_extensions.Annotated[
+ typing.Optional[str],
+ FieldMetadata(alias="fileType"),
+ pydantic.Field(alias="fileType", description="Type of the file, detected based on its content (MIME type)."),
+ ] = None
+ """
+ Type of the file, detected based on its content (MIME type).
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/format.py b/skyvault/skyflow/generated/rest/types/format.py
deleted file mode 100644
index a12992cd..00000000
--- a/skyvault/skyflow/generated/rest/types/format.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from .format_masked_item import FormatMaskedItem
-from .format_plaintext_item import FormatPlaintextItem
-from .format_redacted_item import FormatRedactedItem
-
-
-class Format(UniversalBaseModel):
- """
- Mapping of preferred data formatting options to entity types. Returned values are dependent on the configuration of the vault storing the data and the permissions of the user or account making the request.
- """
-
- redacted: typing.Optional[typing.List[FormatRedactedItem]] = pydantic.Field(default=None)
- """
- Entity types to fully redact.
- """
-
- masked: typing.Optional[typing.List[FormatMaskedItem]] = pydantic.Field(default=None)
- """
- Entity types to mask.
- """
-
- plaintext: typing.Optional[typing.List[FormatPlaintextItem]] = pydantic.Field(default=None)
- """
- Entity types to return in plaintext.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/format_masked_item.py b/skyvault/skyflow/generated/rest/types/format_masked_item.py
deleted file mode 100644
index eeae9770..00000000
--- a/skyvault/skyflow/generated/rest/types/format_masked_item.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-FormatMaskedItem = typing.Union[
- typing.Literal[
- "age",
- "bank_account",
- "credit_card",
- "credit_card_expiration",
- "cvv",
- "date",
- "date_interval",
- "dob",
- "driver_license",
- "email_address",
- "healthcare_number",
- "ip_address",
- "location",
- "name",
- "numerical_pii",
- "phone_number",
- "ssn",
- "url",
- "vehicle_id",
- "medical_code",
- "name_family",
- "name_given",
- "account_number",
- "event",
- "filename",
- "gender",
- "language",
- "location_address",
- "location_city",
- "location_coordinate",
- "location_country",
- "location_state",
- "location_zip",
- "marital_status",
- "money",
- "name_medical_professional",
- "occupation",
- "organization",
- "organization_medical_facility",
- "origin",
- "passport_number",
- "password",
- "physical_attribute",
- "political_affiliation",
- "religion",
- "time",
- "username",
- "zodiac_sign",
- "blood_type",
- "condition",
- "dose",
- "drug",
- "injury",
- "medical_process",
- "statistics",
- "routing_number",
- "corporate_action",
- "financial_metric",
- "product",
- "trend",
- "duration",
- "location_address_street",
- "all",
- "sexuality",
- "effect",
- "project",
- "organization_id",
- "day",
- "month",
- "year",
- ],
- typing.Any,
-]
diff --git a/skyvault/skyflow/generated/rest/types/format_plaintext_item.py b/skyvault/skyflow/generated/rest/types/format_plaintext_item.py
deleted file mode 100644
index 62dfc4bc..00000000
--- a/skyvault/skyflow/generated/rest/types/format_plaintext_item.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-FormatPlaintextItem = typing.Union[
- typing.Literal[
- "age",
- "bank_account",
- "credit_card",
- "credit_card_expiration",
- "cvv",
- "date",
- "date_interval",
- "dob",
- "driver_license",
- "email_address",
- "healthcare_number",
- "ip_address",
- "location",
- "name",
- "numerical_pii",
- "phone_number",
- "ssn",
- "url",
- "vehicle_id",
- "medical_code",
- "name_family",
- "name_given",
- "account_number",
- "event",
- "filename",
- "gender",
- "language",
- "location_address",
- "location_city",
- "location_coordinate",
- "location_country",
- "location_state",
- "location_zip",
- "marital_status",
- "money",
- "name_medical_professional",
- "occupation",
- "organization",
- "organization_medical_facility",
- "origin",
- "passport_number",
- "password",
- "physical_attribute",
- "political_affiliation",
- "religion",
- "time",
- "username",
- "zodiac_sign",
- "blood_type",
- "condition",
- "dose",
- "drug",
- "injury",
- "medical_process",
- "statistics",
- "routing_number",
- "corporate_action",
- "financial_metric",
- "product",
- "trend",
- "duration",
- "location_address_street",
- "all",
- "sexuality",
- "effect",
- "project",
- "organization_id",
- "day",
- "month",
- "year",
- ],
- typing.Any,
-]
diff --git a/skyvault/skyflow/generated/rest/types/format_redacted_item.py b/skyvault/skyflow/generated/rest/types/format_redacted_item.py
deleted file mode 100644
index d2aee020..00000000
--- a/skyvault/skyflow/generated/rest/types/format_redacted_item.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-FormatRedactedItem = typing.Union[
- typing.Literal[
- "age",
- "bank_account",
- "credit_card",
- "credit_card_expiration",
- "cvv",
- "date",
- "date_interval",
- "dob",
- "driver_license",
- "email_address",
- "healthcare_number",
- "ip_address",
- "location",
- "name",
- "numerical_pii",
- "phone_number",
- "ssn",
- "url",
- "vehicle_id",
- "medical_code",
- "name_family",
- "name_given",
- "account_number",
- "event",
- "filename",
- "gender",
- "language",
- "location_address",
- "location_city",
- "location_coordinate",
- "location_country",
- "location_state",
- "location_zip",
- "marital_status",
- "money",
- "name_medical_professional",
- "occupation",
- "organization",
- "organization_medical_facility",
- "origin",
- "passport_number",
- "password",
- "physical_attribute",
- "political_affiliation",
- "religion",
- "time",
- "username",
- "zodiac_sign",
- "blood_type",
- "condition",
- "dose",
- "drug",
- "injury",
- "medical_process",
- "statistics",
- "routing_number",
- "corporate_action",
- "financial_metric",
- "product",
- "trend",
- "duration",
- "location_address_street",
- "all",
- "sexuality",
- "effect",
- "project",
- "organization_id",
- "day",
- "month",
- "year",
- ],
- typing.Any,
-]
diff --git a/skyvault/skyflow/generated/rest/types/get_field_records.py b/skyvault/skyflow/generated/rest/types/get_field_records.py
new file mode 100644
index 00000000..8b2c65e9
--- /dev/null
+++ b/skyvault/skyflow/generated/rest/types/get_field_records.py
@@ -0,0 +1,45 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+import typing_extensions
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from ..core.serialization import FieldMetadata
+from .file_metadata import FileMetadata
+
+
+class GetFieldRecords(UniversalBaseModel):
+ """
+ Record values and tokens for Get and BulkGet.
+ """
+
+ fields: typing.Optional[typing.Dict[str, typing.Any]] = pydantic.Field(default=None)
+ """
+ Fields and values for the record. For example, `{'field_1':'value_1', 'field_2':'value_2'}`.
+ """
+
+ tokens: typing.Optional[typing.Dict[str, typing.Any]] = pydantic.Field(default=None)
+ """
+ Fields and tokens for the record. For example, `{'field_1':'token_1', 'field_2':'token_2'}`.
+ """
+
+ file_metadata: typing_extensions.Annotated[
+ typing.Optional[typing.Dict[str, FileMetadata]],
+ FieldMetadata(alias="fileMetadata"),
+ pydantic.Field(
+ alias="fileMetadata", description="Metadata for the uploaded file, keyed by dynamic column name."
+ ),
+ ] = None
+ """
+ Metadata for the uploaded file, keyed by dynamic column name.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/v_1_get_query_response.py b/skyvault/skyflow/generated/rest/types/get_query_response.py
similarity index 74%
rename from skyvault/skyflow/generated/rest/types/v_1_get_query_response.py
rename to skyvault/skyflow/generated/rest/types/get_query_response.py
index 0edf0513..d2035997 100644
--- a/skyvault/skyflow/generated/rest/types/v_1_get_query_response.py
+++ b/skyvault/skyflow/generated/rest/types/get_query_response.py
@@ -4,11 +4,11 @@
import pydantic
from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from .v_1_field_records import V1FieldRecords
+from .field_records import FieldRecords
-class V1GetQueryResponse(UniversalBaseModel):
- records: typing.Optional[typing.List[V1FieldRecords]] = pydantic.Field(default=None)
+class GetQueryResponse(UniversalBaseModel):
+ records: typing.Optional[typing.List[FieldRecords]] = pydantic.Field(default=None)
"""
Records returned by the query.
"""
diff --git a/skyvault/skyflow/generated/rest/types/googlerpc_status.py b/skyvault/skyflow/generated/rest/types/googlerpc_status.py
deleted file mode 100644
index f0a885b4..00000000
--- a/skyvault/skyflow/generated/rest/types/googlerpc_status.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from .protobuf_any import ProtobufAny
-
-
-class GooglerpcStatus(UniversalBaseModel):
- code: typing.Optional[int] = None
- message: typing.Optional[str] = None
- details: typing.Optional[typing.List[ProtobufAny]] = None
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/http_code.py b/skyvault/skyflow/generated/rest/types/http_code.py
index 5fc9a3fb..a40fefff 100644
--- a/skyvault/skyflow/generated/rest/types/http_code.py
+++ b/skyvault/skyflow/generated/rest/types/http_code.py
@@ -1,3 +1,6 @@
# This file was auto-generated by Fern from our API Definition.
HttpCode = int
+"""
+HTTP status codes. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Status.
+"""
diff --git a/skyvault/skyflow/generated/rest/types/deidentify_file_response.py b/skyvault/skyflow/generated/rest/types/insert_record_response.py
similarity index 68%
rename from skyvault/skyflow/generated/rest/types/deidentify_file_response.py
rename to skyvault/skyflow/generated/rest/types/insert_record_response.py
index 4c4503f4..384d5f8f 100644
--- a/skyvault/skyflow/generated/rest/types/deidentify_file_response.py
+++ b/skyvault/skyflow/generated/rest/types/insert_record_response.py
@@ -4,16 +4,13 @@
import pydantic
from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from .record_meta_properties import RecordMetaProperties
-class DeidentifyFileResponse(UniversalBaseModel):
+class InsertRecordResponse(UniversalBaseModel):
+ records: typing.Optional[typing.List[RecordMetaProperties]] = pydantic.Field(default=None)
"""
- Response to deidentify a file.
- """
-
- run_id: typing.Optional[str] = pydantic.Field(default=None)
- """
- Status URL for the Detect run.
+ Inserted records.
"""
if IS_PYDANTIC_V2:
diff --git a/skyvault/skyflow/generated/rest/types/locations.py b/skyvault/skyflow/generated/rest/types/locations.py
deleted file mode 100644
index 7b8ba88e..00000000
--- a/skyvault/skyflow/generated/rest/types/locations.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-
-
-class Locations(UniversalBaseModel):
- """
- Locations of an entity in the text.
- """
-
- start_index: typing.Optional[int] = pydantic.Field(default=None)
- """
- Index of the first character of the string in the original text.
- """
-
- end_index: typing.Optional[int] = pydantic.Field(default=None)
- """
- Index of the last character of the string in the original text.
- """
-
- start_index_processed: typing.Optional[int] = pydantic.Field(default=None)
- """
- Index of the first character of the string in the processed text.
- """
-
- end_index_processed: typing.Optional[int] = pydantic.Field(default=None)
- """
- Index of the last character of the string in the processed text.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/protobuf_any.py b/skyvault/skyflow/generated/rest/types/protobuf_any.py
deleted file mode 100644
index 9062870c..00000000
--- a/skyvault/skyflow/generated/rest/types/protobuf_any.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-import typing_extensions
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from ..core.serialization import FieldMetadata
-
-
-class ProtobufAny(UniversalBaseModel):
- type: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="@type")] = None
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/v_1_record_meta_properties.py b/skyvault/skyflow/generated/rest/types/record_meta_properties.py
similarity index 80%
rename from skyvault/skyflow/generated/rest/types/v_1_record_meta_properties.py
rename to skyvault/skyflow/generated/rest/types/record_meta_properties.py
index bc51f5c5..e221bff7 100644
--- a/skyvault/skyflow/generated/rest/types/v_1_record_meta_properties.py
+++ b/skyvault/skyflow/generated/rest/types/record_meta_properties.py
@@ -6,13 +6,13 @@
from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-class V1RecordMetaProperties(UniversalBaseModel):
+class RecordMetaProperties(UniversalBaseModel):
skyflow_id: typing.Optional[str] = pydantic.Field(default=None)
"""
ID of the inserted record.
"""
- tokens: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None)
+ tokens: typing.Optional[typing.Dict[str, typing.Any]] = pydantic.Field(default=None)
"""
Tokens for the record.
"""
diff --git a/skyvault/skyflow/generated/rest/types/redaction_enum_redaction.py b/skyvault/skyflow/generated/rest/types/redaction_enum_redaction.py
deleted file mode 100644
index 25529a7d..00000000
--- a/skyvault/skyflow/generated/rest/types/redaction_enum_redaction.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-RedactionEnumRedaction = typing.Union[typing.Literal["DEFAULT", "REDACTED", "MASKED", "PLAIN_TEXT"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/types/reidentified_file_output.py b/skyvault/skyflow/generated/rest/types/reidentified_file_output.py
deleted file mode 100644
index c7f8544e..00000000
--- a/skyvault/skyflow/generated/rest/types/reidentified_file_output.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from .reidentified_file_output_processed_file_extension import ReidentifiedFileOutputProcessedFileExtension
-
-
-class ReidentifiedFileOutput(UniversalBaseModel):
- """
- Details of output files. Files are specified as Base64-encoded data.
- """
-
- processed_file: typing.Optional[str] = pydantic.Field(default=None)
- """
- File content in Base64 format.
- """
-
- processed_file_type: typing.Optional[typing.Literal["reidentified_file"]] = pydantic.Field(default=None)
- """
- Type of the processed file.
- """
-
- processed_file_extension: typing.Optional[ReidentifiedFileOutputProcessedFileExtension] = pydantic.Field(
- default=None
- )
- """
- Extension of the processed file.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/reidentify_file_response.py b/skyvault/skyflow/generated/rest/types/reidentify_file_response.py
deleted file mode 100644
index ef076c72..00000000
--- a/skyvault/skyflow/generated/rest/types/reidentify_file_response.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from .reidentified_file_output import ReidentifiedFileOutput
-from .reidentify_file_response_output_type import ReidentifyFileResponseOutputType
-from .reidentify_file_response_status import ReidentifyFileResponseStatus
-
-
-class ReidentifyFileResponse(UniversalBaseModel):
- """
- Response to get the status & response of a file re-identification request.
- """
-
- status: typing.Optional[ReidentifyFileResponseStatus] = pydantic.Field(default=None)
- """
- Status of the operation.
- """
-
- output_type: typing.Optional[ReidentifyFileResponseOutputType] = pydantic.Field(default=None)
- """
- Format of the output file.
- """
-
- output: typing.Optional[ReidentifiedFileOutput] = None
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/reidentify_file_response_output_type.py b/skyvault/skyflow/generated/rest/types/reidentify_file_response_output_type.py
deleted file mode 100644
index b7b9e8c4..00000000
--- a/skyvault/skyflow/generated/rest/types/reidentify_file_response_output_type.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-ReidentifyFileResponseOutputType = typing.Union[typing.Literal["UNKNOWN", "BASE64"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/types/reidentify_file_response_status.py b/skyvault/skyflow/generated/rest/types/reidentify_file_response_status.py
deleted file mode 100644
index ffa5dfc3..00000000
--- a/skyvault/skyflow/generated/rest/types/reidentify_file_response_status.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-ReidentifyFileResponseStatus = typing.Union[typing.Literal["UNKNOWN", "FAILED", "SUCCESS", "IN_PROGRESS"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/types/request_action_type.py b/skyvault/skyflow/generated/rest/types/request_action_type.py
deleted file mode 100644
index c10fe1ce..00000000
--- a/skyvault/skyflow/generated/rest/types/request_action_type.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-RequestActionType = typing.Union[
- typing.Literal[
- "NONE",
- "ASSIGN",
- "CREATE",
- "DELETE",
- "EXECUTE",
- "LIST",
- "READ",
- "UNASSIGN",
- "UPDATE",
- "VALIDATE",
- "LOGIN",
- "ROTATE",
- "SCHEDULEROTATION",
- "SCHEDULEROTATIONALERT",
- "IMPORT",
- "GETIMPORTPARAMETERS",
- "PING",
- "GETCLOUDPROVIDER",
- ],
- typing.Any,
-]
diff --git a/skyvault/skyflow/generated/rest/types/shift_dates.py b/skyvault/skyflow/generated/rest/types/shift_dates.py
deleted file mode 100644
index 7a1af257..00000000
--- a/skyvault/skyflow/generated/rest/types/shift_dates.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from .shift_dates_entity_types_item import ShiftDatesEntityTypesItem
-
-
-class ShiftDates(UniversalBaseModel):
- """
- Shift dates by a specified number of days.
- """
-
- min_days: typing.Optional[int] = pydantic.Field(default=None)
- """
- Minimum number of days to shift the date by.
- """
-
- max_days: typing.Optional[int] = pydantic.Field(default=None)
- """
- Maximum number of days to shift the date by.
- """
-
- entity_types: typing.Optional[typing.List[ShiftDatesEntityTypesItem]] = pydantic.Field(default=None)
- """
- Entity types to shift dates for.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/shift_dates_entity_types_item.py b/skyvault/skyflow/generated/rest/types/shift_dates_entity_types_item.py
deleted file mode 100644
index b0f10d19..00000000
--- a/skyvault/skyflow/generated/rest/types/shift_dates_entity_types_item.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-ShiftDatesEntityTypesItem = typing.Union[typing.Literal["date", "date_interval", "dob"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/types/token_type_mapping.py b/skyvault/skyflow/generated/rest/types/token_type_mapping.py
deleted file mode 100644
index 5644fd01..00000000
--- a/skyvault/skyflow/generated/rest/types/token_type_mapping.py
+++ /dev/null
@@ -1,47 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from .token_type_mapping_default import TokenTypeMappingDefault
-from .token_type_mapping_entity_only_item import TokenTypeMappingEntityOnlyItem
-from .token_type_mapping_entity_unq_counter_item import TokenTypeMappingEntityUnqCounterItem
-from .token_type_mapping_vault_token_item import TokenTypeMappingVaultTokenItem
-
-
-class TokenTypeMapping(UniversalBaseModel):
- """
- Mapping of token types to detected entities.
- """
-
- vault_token: typing.Optional[typing.List[TokenTypeMappingVaultTokenItem]] = pydantic.Field(default=None)
- """
- Entity types to replace with vault tokens.
- """
-
- entity_only: typing.Optional[typing.List[TokenTypeMappingEntityOnlyItem]] = pydantic.Field(default=None)
- """
- Entity types to replace with entity tokens.
- """
-
- entity_unq_counter: typing.Optional[typing.List[TokenTypeMappingEntityUnqCounterItem]] = pydantic.Field(
- default=None
- )
- """
- Entity types to replace with entity tokens with unique counters.
- """
-
- default: typing.Optional[TokenTypeMappingDefault] = pydantic.Field(default=None)
- """
- Default token type to generate for detected entities.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/token_type_mapping_default.py b/skyvault/skyflow/generated/rest/types/token_type_mapping_default.py
deleted file mode 100644
index 36a9e4ba..00000000
--- a/skyvault/skyflow/generated/rest/types/token_type_mapping_default.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-TokenTypeMappingDefault = typing.Union[typing.Literal["entity_unq_counter", "entity_only", "vault_token"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/types/token_type_mapping_entity_only_item.py b/skyvault/skyflow/generated/rest/types/token_type_mapping_entity_only_item.py
deleted file mode 100644
index d3309ab9..00000000
--- a/skyvault/skyflow/generated/rest/types/token_type_mapping_entity_only_item.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-TokenTypeMappingEntityOnlyItem = typing.Union[
- typing.Literal[
- "age",
- "bank_account",
- "credit_card",
- "credit_card_expiration",
- "cvv",
- "date",
- "date_interval",
- "dob",
- "driver_license",
- "email_address",
- "healthcare_number",
- "ip_address",
- "location",
- "name",
- "numerical_pii",
- "phone_number",
- "ssn",
- "url",
- "vehicle_id",
- "medical_code",
- "name_family",
- "name_given",
- "account_number",
- "event",
- "filename",
- "gender",
- "language",
- "location_address",
- "location_city",
- "location_coordinate",
- "location_country",
- "location_state",
- "location_zip",
- "marital_status",
- "money",
- "name_medical_professional",
- "occupation",
- "organization",
- "organization_medical_facility",
- "origin",
- "passport_number",
- "password",
- "physical_attribute",
- "political_affiliation",
- "religion",
- "time",
- "username",
- "zodiac_sign",
- "blood_type",
- "condition",
- "dose",
- "drug",
- "injury",
- "medical_process",
- "statistics",
- "routing_number",
- "corporate_action",
- "financial_metric",
- "product",
- "trend",
- "duration",
- "location_address_street",
- "all",
- "sexuality",
- "effect",
- "project",
- "organization_id",
- "day",
- "month",
- "year",
- ],
- typing.Any,
-]
diff --git a/skyvault/skyflow/generated/rest/types/token_type_mapping_entity_unq_counter_item.py b/skyvault/skyflow/generated/rest/types/token_type_mapping_entity_unq_counter_item.py
deleted file mode 100644
index 219f79ac..00000000
--- a/skyvault/skyflow/generated/rest/types/token_type_mapping_entity_unq_counter_item.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-TokenTypeMappingEntityUnqCounterItem = typing.Union[
- typing.Literal[
- "age",
- "bank_account",
- "credit_card",
- "credit_card_expiration",
- "cvv",
- "date",
- "date_interval",
- "dob",
- "driver_license",
- "email_address",
- "healthcare_number",
- "ip_address",
- "location",
- "name",
- "numerical_pii",
- "phone_number",
- "ssn",
- "url",
- "vehicle_id",
- "medical_code",
- "name_family",
- "name_given",
- "account_number",
- "event",
- "filename",
- "gender",
- "language",
- "location_address",
- "location_city",
- "location_coordinate",
- "location_country",
- "location_state",
- "location_zip",
- "marital_status",
- "money",
- "name_medical_professional",
- "occupation",
- "organization",
- "organization_medical_facility",
- "origin",
- "passport_number",
- "password",
- "physical_attribute",
- "political_affiliation",
- "religion",
- "time",
- "username",
- "zodiac_sign",
- "blood_type",
- "condition",
- "dose",
- "drug",
- "injury",
- "medical_process",
- "statistics",
- "routing_number",
- "corporate_action",
- "financial_metric",
- "product",
- "trend",
- "duration",
- "location_address_street",
- "all",
- "sexuality",
- "effect",
- "project",
- "organization_id",
- "day",
- "month",
- "year",
- ],
- typing.Any,
-]
diff --git a/skyvault/skyflow/generated/rest/types/token_type_mapping_vault_token_item.py b/skyvault/skyflow/generated/rest/types/token_type_mapping_vault_token_item.py
deleted file mode 100644
index 17178ea6..00000000
--- a/skyvault/skyflow/generated/rest/types/token_type_mapping_vault_token_item.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-TokenTypeMappingVaultTokenItem = typing.Union[
- typing.Literal[
- "age",
- "bank_account",
- "credit_card",
- "credit_card_expiration",
- "cvv",
- "date",
- "date_interval",
- "dob",
- "driver_license",
- "email_address",
- "healthcare_number",
- "ip_address",
- "location",
- "name",
- "numerical_pii",
- "phone_number",
- "ssn",
- "url",
- "vehicle_id",
- "medical_code",
- "name_family",
- "name_given",
- "account_number",
- "event",
- "filename",
- "gender",
- "language",
- "location_address",
- "location_city",
- "location_coordinate",
- "location_country",
- "location_state",
- "location_zip",
- "marital_status",
- "money",
- "name_medical_professional",
- "occupation",
- "organization",
- "organization_medical_facility",
- "origin",
- "passport_number",
- "password",
- "physical_attribute",
- "political_affiliation",
- "religion",
- "time",
- "username",
- "zodiac_sign",
- "blood_type",
- "condition",
- "dose",
- "drug",
- "injury",
- "medical_process",
- "statistics",
- "routing_number",
- "corporate_action",
- "financial_metric",
- "product",
- "trend",
- "duration",
- "location_address_street",
- "all",
- "sexuality",
- "effect",
- "project",
- "organization_id",
- "day",
- "month",
- "year",
- ],
- typing.Any,
-]
diff --git a/skyvault/skyflow/generated/rest/types/tokenize_record_request.py b/skyvault/skyflow/generated/rest/types/tokenize_record_request.py
new file mode 100644
index 00000000..931acaee
--- /dev/null
+++ b/skyvault/skyflow/generated/rest/types/tokenize_record_request.py
@@ -0,0 +1,46 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+import typing_extensions
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from ..core.serialization import FieldMetadata
+
+
+class TokenizeRecordRequest(UniversalBaseModel):
+ value: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Existing value to return a token for. Must be specified with either `columnGroup` or both `table` and `column`.
+ """
+
+ table: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Name of the table that the value belongs to. Must be specified with `column`. Can't be specified with `columnGroup`.
+ """
+
+ column: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Name of the column that the value belongs to. Must be specified with `table`. Can't be specified with `columnGroup`.
+ """
+
+ column_group: typing_extensions.Annotated[
+ typing.Optional[str],
+ FieldMetadata(alias="columnGroup"),
+ pydantic.Field(
+ alias="columnGroup",
+ description="Name of the column group that the value belongs to. Can't be specified with `table` or `column`.",
+ ),
+ ] = None
+ """
+ Name of the column group that the value belongs to. Can't be specified with `table` or `column`.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/v_1_tokenize_record_response.py b/skyvault/skyflow/generated/rest/types/tokenize_record_response.py
similarity index 81%
rename from skyvault/skyflow/generated/rest/types/v_1_tokenize_record_response.py
rename to skyvault/skyflow/generated/rest/types/tokenize_record_response.py
index fd449283..9f61cb78 100644
--- a/skyvault/skyflow/generated/rest/types/v_1_tokenize_record_response.py
+++ b/skyvault/skyflow/generated/rest/types/tokenize_record_response.py
@@ -6,8 +6,8 @@
from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-class V1TokenizeRecordResponse(UniversalBaseModel):
- token: typing.Optional[str] = pydantic.Field(default=None)
+class TokenizeRecordResponse(UniversalBaseModel):
+ token: str = pydantic.Field()
"""
Token corresponding to a value.
"""
diff --git a/skyvault/skyflow/generated/rest/types/v_1_tokenize_response.py b/skyvault/skyflow/generated/rest/types/tokenize_response.py
similarity index 71%
rename from skyvault/skyflow/generated/rest/types/v_1_tokenize_response.py
rename to skyvault/skyflow/generated/rest/types/tokenize_response.py
index f882cc24..3455ffa4 100644
--- a/skyvault/skyflow/generated/rest/types/v_1_tokenize_response.py
+++ b/skyvault/skyflow/generated/rest/types/tokenize_response.py
@@ -4,11 +4,11 @@
import pydantic
from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from .v_1_tokenize_record_response import V1TokenizeRecordResponse
+from .tokenize_record_response import TokenizeRecordResponse
-class V1TokenizeResponse(UniversalBaseModel):
- records: typing.Optional[typing.List[V1TokenizeRecordResponse]] = pydantic.Field(default=None)
+class TokenizeResponse(UniversalBaseModel):
+ records: typing.List[TokenizeRecordResponse] = pydantic.Field()
"""
Tokens corresponding to the specified values.
"""
diff --git a/skyvault/skyflow/generated/rest/types/v_1_update_record_response.py b/skyvault/skyflow/generated/rest/types/update_record_response.py
similarity index 79%
rename from skyvault/skyflow/generated/rest/types/v_1_update_record_response.py
rename to skyvault/skyflow/generated/rest/types/update_record_response.py
index c17a3933..911f3f37 100644
--- a/skyvault/skyflow/generated/rest/types/v_1_update_record_response.py
+++ b/skyvault/skyflow/generated/rest/types/update_record_response.py
@@ -6,13 +6,13 @@
from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-class V1UpdateRecordResponse(UniversalBaseModel):
+class UpdateRecordResponse(UniversalBaseModel):
skyflow_id: typing.Optional[str] = pydantic.Field(default=None)
"""
ID of the updated record.
"""
- tokens: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None)
+ tokens: typing.Optional[typing.Dict[str, typing.Any]] = pydantic.Field(default=None)
"""
Tokens for the record.
"""
diff --git a/skyvault/skyflow/generated/rest/types/upload_file_response_v2.py b/skyvault/skyflow/generated/rest/types/upload_file_response_v2.py
new file mode 100644
index 00000000..f6d1134f
--- /dev/null
+++ b/skyvault/skyflow/generated/rest/types/upload_file_response_v2.py
@@ -0,0 +1,41 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+import pydantic
+import typing_extensions
+from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
+from ..core.serialization import FieldMetadata
+from .file_metadata import FileMetadata
+
+
+class UploadFileResponseV2(UniversalBaseModel):
+ skyflow_id: typing_extensions.Annotated[
+ typing.Optional[str],
+ FieldMetadata(alias="skyflowID"),
+ pydantic.Field(alias="skyflowID", description="ID of the record to update."),
+ ] = None
+ """
+ ID of the record to update.
+ """
+
+ file_metadata: typing_extensions.Annotated[
+ typing.Optional[typing.Dict[str, FileMetadata]],
+ FieldMetadata(alias="fileMetadata"),
+ pydantic.Field(
+ alias="fileMetadata",
+ description="Metadata for the uploaded file with keys based on the name of the column containing the file.",
+ ),
+ ] = None
+ """
+ Metadata for the uploaded file with keys based on the name of the column containing the file.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/v_1_audit_after_options.py b/skyvault/skyflow/generated/rest/types/v_1_audit_after_options.py
deleted file mode 100644
index 6d10157e..00000000
--- a/skyvault/skyflow/generated/rest/types/v_1_audit_after_options.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-import typing_extensions
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from ..core.serialization import FieldMetadata
-
-
-class V1AuditAfterOptions(UniversalBaseModel):
- timestamp: typing.Optional[str] = pydantic.Field(default=None)
- """
- Timestamp provided in the previous audit response's `nextOps` attribute. An alternate way to manage response pagination. Can't be used with `sortOps` or `offset`. For the first request in a series of audit requests, leave blank.
- """
-
- change_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="changeID")] = pydantic.Field(
- default=None
- )
- """
- Change ID provided in the previous audit response's `nextOps` attribute. An alternate way to manage response pagination. Can't be used with `sortOps` or `offset`. For the first request in a series of audit requests, leave blank.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/v_1_audit_event_response.py b/skyvault/skyflow/generated/rest/types/v_1_audit_event_response.py
deleted file mode 100644
index d82e8999..00000000
--- a/skyvault/skyflow/generated/rest/types/v_1_audit_event_response.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from .audit_event_data import AuditEventData
-
-
-class V1AuditEventResponse(UniversalBaseModel):
- """
- Contains fields for defining Response Properties.
- """
-
- code: typing.Optional[int] = pydantic.Field(default=None)
- """
- The status of the overall operation.
- """
-
- message: typing.Optional[str] = pydantic.Field(default=None)
- """
- The status message for the overall operation.
- """
-
- data: typing.Optional[AuditEventData] = None
- timestamp: typing.Optional[str] = pydantic.Field(default=None)
- """
- time when this response is generated, use extention method to set it.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/v_1_audit_response.py b/skyvault/skyflow/generated/rest/types/v_1_audit_response.py
deleted file mode 100644
index fe0b358a..00000000
--- a/skyvault/skyflow/generated/rest/types/v_1_audit_response.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-import typing_extensions
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from ..core.serialization import FieldMetadata
-from .v_1_audit_after_options import V1AuditAfterOptions
-from .v_1_audit_response_event import V1AuditResponseEvent
-
-
-class V1AuditResponse(UniversalBaseModel):
- event: typing.Optional[typing.List[V1AuditResponseEvent]] = pydantic.Field(default=None)
- """
- Events matching the query.
- """
-
- next_ops: typing_extensions.Annotated[typing.Optional[V1AuditAfterOptions], FieldMetadata(alias="nextOps")] = None
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/v_1_audit_response_event.py b/skyvault/skyflow/generated/rest/types/v_1_audit_response_event.py
deleted file mode 100644
index dbea54a2..00000000
--- a/skyvault/skyflow/generated/rest/types/v_1_audit_response_event.py
+++ /dev/null
@@ -1,50 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-import typing_extensions
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from ..core.serialization import FieldMetadata
-from .audit_event_context import AuditEventContext
-from .v_1_audit_event_response import V1AuditEventResponse
-from .v_1_audit_response_event_request import V1AuditResponseEventRequest
-
-
-class V1AuditResponseEvent(UniversalBaseModel):
- """
- Audit event details.
- """
-
- context: typing.Optional[AuditEventContext] = None
- request: typing.Optional[V1AuditResponseEventRequest] = None
- response: typing.Optional[V1AuditEventResponse] = None
- parent_account_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="parentAccountID")] = (
- pydantic.Field(default=None)
- )
- """
- Parent account ID of the account that made the request, if any.
- """
-
- account_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="accountID")] = pydantic.Field(
- default=None
- )
- """
- ID of the account that made the request.
- """
-
- resource_i_ds: typing_extensions.Annotated[
- typing.Optional[typing.List[str]], FieldMetadata(alias="resourceIDs")
- ] = pydantic.Field(default=None)
- """
- IDs for resources involved in the event. Presented in `{resourceType}/{resourceID}` format. For example, `VAULT/cd1d815aa09b4cbfbb803bd20349f202`.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/v_1_audit_response_event_request.py b/skyvault/skyflow/generated/rest/types/v_1_audit_response_event_request.py
deleted file mode 100644
index 6127818d..00000000
--- a/skyvault/skyflow/generated/rest/types/v_1_audit_response_event_request.py
+++ /dev/null
@@ -1,67 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-import typing_extensions
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from ..core.serialization import FieldMetadata
-from .audit_event_audit_resource_type import AuditEventAuditResourceType
-from .audit_event_data import AuditEventData
-from .audit_event_http_info import AuditEventHttpInfo
-from .request_action_type import RequestActionType
-
-
-class V1AuditResponseEventRequest(UniversalBaseModel):
- """
- Contains fields for defining Request Properties.
- """
-
- data: typing.Optional[AuditEventData] = None
- api_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="apiName")] = pydantic.Field(
- default=None
- )
- """
- API name.
- """
-
- workspace_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="workspaceID")] = (
- pydantic.Field(default=None)
- )
- """
- The workspaceID (if any) of the request.
- """
-
- vault_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="vaultID")] = pydantic.Field(
- default=None
- )
- """
- The vaultID (if any) of the request.
- """
-
- tags: typing.Optional[typing.List[str]] = pydantic.Field(default=None)
- """
- Tags associated with the event. To provide better search capabilities. Like login.
- """
-
- timestamp: typing.Optional[str] = pydantic.Field(default=None)
- """
- time when this request is generated, use extention method to set it.
- """
-
- action_type: typing_extensions.Annotated[typing.Optional[RequestActionType], FieldMetadata(alias="actionType")] = (
- None
- )
- resource_type: typing_extensions.Annotated[
- typing.Optional[AuditEventAuditResourceType], FieldMetadata(alias="resourceType")
- ] = None
- http_info: typing_extensions.Annotated[typing.Optional[AuditEventHttpInfo], FieldMetadata(alias="httpInfo")] = None
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/v_1_batch_record.py b/skyvault/skyflow/generated/rest/types/v_1_batch_record.py
deleted file mode 100644
index d531fc5e..00000000
--- a/skyvault/skyflow/generated/rest/types/v_1_batch_record.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-import typing_extensions
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from ..core.serialization import FieldMetadata
-from .batch_record_method import BatchRecordMethod
-from .redaction_enum_redaction import RedactionEnumRedaction
-
-
-class V1BatchRecord(UniversalBaseModel):
- fields: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None)
- """
- Field and value key pairs. For example, `{'field_1':'value_1', 'field_2':'value_2'}`. Only valid when `method` is `POST` or `PUT`.
- """
-
- table_name: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="tableName")] = pydantic.Field(
- default=None
- )
- """
- Name of the table to perform the operation on.
- """
-
- method: typing.Optional[BatchRecordMethod] = None
- batch_id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="batchID")] = pydantic.Field(
- default=None
- )
- """
- ID to group operations by. Operations in the same group are executed sequentially.
- """
-
- redaction: typing.Optional[RedactionEnumRedaction] = None
- tokenization: typing.Optional[bool] = pydantic.Field(default=None)
- """
- If `true`, this operation returns tokens for fields with tokenization enabled. Only applicable if `skyflow_id` values are specified.
- """
-
- id: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="ID")] = pydantic.Field(default=None)
- """
- `skyflow_id` for the record. Only valid when `method` is `GET`, `DELETE`, or `PUT`.
- """
-
- download_url: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="downloadURL")] = (
- pydantic.Field(default=None)
- )
- """
- If `true`, returns download URLs for fields with a file data type. URLs are valid for 15 minutes. If virus scanning is enabled, only returns if the file is clean.
- """
-
- upsert: typing.Optional[str] = pydantic.Field(default=None)
- """
- Column that stores primary keys for upsert operations. The column must be marked as unique in the vault schema. Only valid when `method` is `POST`.
- """
-
- tokens: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None)
- """
- Fields and tokens for the record. For example, `{'field_1':'token_1', 'field_2':'token_2'}`.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/v_1_bin_list_response.py b/skyvault/skyflow/generated/rest/types/v_1_bin_list_response.py
deleted file mode 100644
index 24d7fad7..00000000
--- a/skyvault/skyflow/generated/rest/types/v_1_bin_list_response.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from .v_1_card import V1Card
-
-
-class V1BinListResponse(UniversalBaseModel):
- """
- Response to the Get BIN request.
- """
-
- cards_data: typing.Optional[typing.List[V1Card]] = pydantic.Field(default=None)
- """
- Card metadata associated with the specified BIN.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/v_1_byot.py b/skyvault/skyflow/generated/rest/types/v_1_byot.py
deleted file mode 100644
index 3c03bdac..00000000
--- a/skyvault/skyflow/generated/rest/types/v_1_byot.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-V1Byot = typing.Union[typing.Literal["DISABLE", "ENABLE", "ENABLE_STRICT"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/types/v_1_card.py b/skyvault/skyflow/generated/rest/types/v_1_card.py
deleted file mode 100644
index 1c862169..00000000
--- a/skyvault/skyflow/generated/rest/types/v_1_card.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-import typing_extensions
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from ..core.serialization import FieldMetadata
-
-
-class V1Card(UniversalBaseModel):
- """
- Card metadata of the requested BIN.
- """
-
- bin: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="BIN")] = pydantic.Field(default=None)
- """
- BIN of the card.
- """
-
- issuer_name: typing.Optional[str] = pydantic.Field(default=None)
- """
- Name of the card issuer bank.
- """
-
- country_code: typing.Optional[str] = pydantic.Field(default=None)
- """
- Country code of the card.
- """
-
- currency: typing.Optional[str] = pydantic.Field(default=None)
- """
- Currency of the card.
- """
-
- card_type: typing.Optional[str] = pydantic.Field(default=None)
- """
- Type of the card.
- """
-
- card_category: typing.Optional[str] = pydantic.Field(default=None)
- """
- Category of the card.
- """
-
- card_scheme: typing.Optional[str] = pydantic.Field(default=None)
- """
- Scheme of the card.
- """
-
- card_last_four_digits: typing.Optional[str] = pydantic.Field(default=None)
- """
- Last four digits of the card number.
- """
-
- card_expiry: typing.Optional[str] = pydantic.Field(default=None)
- """
- Expiry date of the card.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/v_1_delete_file_response.py b/skyvault/skyflow/generated/rest/types/v_1_delete_file_response.py
deleted file mode 100644
index 927517e9..00000000
--- a/skyvault/skyflow/generated/rest/types/v_1_delete_file_response.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-
-
-class V1DeleteFileResponse(UniversalBaseModel):
- skyflow_id: typing.Optional[str] = pydantic.Field(default=None)
- """
- ID of the record.
- """
-
- deleted: typing.Optional[bool] = pydantic.Field(default=None)
- """
- If `true`, the file was deleted.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/v_1_file_av_scan_status.py b/skyvault/skyflow/generated/rest/types/v_1_file_av_scan_status.py
deleted file mode 100644
index 78712507..00000000
--- a/skyvault/skyflow/generated/rest/types/v_1_file_av_scan_status.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-V1FileAvScanStatus = typing.Union[
- typing.Literal[
- "SCAN_NONE",
- "SCAN_CLEAN",
- "SCAN_INFECTED",
- "SCAN_DELETED",
- "SCAN_ERROR",
- "SCAN_PENDING",
- "SCAN_UNSCANNABLE",
- "SCAN_FILE_NOT_FOUND",
- "SCAN_INVALID",
- ],
- typing.Any,
-]
diff --git a/skyvault/skyflow/generated/rest/types/v_1_get_file_scan_status_response.py b/skyvault/skyflow/generated/rest/types/v_1_get_file_scan_status_response.py
deleted file mode 100644
index 70801b56..00000000
--- a/skyvault/skyflow/generated/rest/types/v_1_get_file_scan_status_response.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from .v_1_file_av_scan_status import V1FileAvScanStatus
-
-
-class V1GetFileScanStatusResponse(UniversalBaseModel):
- av_scan_status: typing.Optional[V1FileAvScanStatus] = None
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/v_1_insert_record_response.py b/skyvault/skyflow/generated/rest/types/v_1_insert_record_response.py
deleted file mode 100644
index d303a2f9..00000000
--- a/skyvault/skyflow/generated/rest/types/v_1_insert_record_response.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from .v_1_record_meta_properties import V1RecordMetaProperties
-
-
-class V1InsertRecordResponse(UniversalBaseModel):
- records: typing.Optional[typing.List[V1RecordMetaProperties]] = pydantic.Field(default=None)
- """
- Identifiers for the inserted records.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/v_1_member_type.py b/skyvault/skyflow/generated/rest/types/v_1_member_type.py
deleted file mode 100644
index 4f862413..00000000
--- a/skyvault/skyflow/generated/rest/types/v_1_member_type.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-V1MemberType = typing.Union[typing.Literal["NONE", "USER", "SERVICE_ACCOUNT"], typing.Any]
diff --git a/skyvault/skyflow/generated/rest/types/v_1_tokenize_record_request.py b/skyvault/skyflow/generated/rest/types/v_1_tokenize_record_request.py
deleted file mode 100644
index 1801aeb7..00000000
--- a/skyvault/skyflow/generated/rest/types/v_1_tokenize_record_request.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-import typing_extensions
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from ..core.serialization import FieldMetadata
-
-
-class V1TokenizeRecordRequest(UniversalBaseModel):
- value: typing.Optional[str] = pydantic.Field(default=None)
- """
- Existing value to return a token for.
- """
-
- column_group: typing_extensions.Annotated[typing.Optional[str], FieldMetadata(alias="columnGroup")] = (
- pydantic.Field(default=None)
- )
- """
- Name of the column group that the value belongs to.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/v_1_vault_field_mapping.py b/skyvault/skyflow/generated/rest/types/v_1_vault_field_mapping.py
deleted file mode 100644
index c681b94d..00000000
--- a/skyvault/skyflow/generated/rest/types/v_1_vault_field_mapping.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-
-
-class V1VaultFieldMapping(UniversalBaseModel):
- """
- Mapping of the fields in the vault to the fields to use for the lookup.
- """
-
- card_number: typing.Optional[str] = pydantic.Field(default=None)
- """
- Name of the column that stores the card number.
- """
-
- card_last_four_digits: typing.Optional[str] = pydantic.Field(default=None)
- """
- Name of the column that stores the card number suffix.
- """
-
- card_expiry: typing.Optional[str] = pydantic.Field(default=None)
- """
- Name of the column that stores the expiry date.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/v_1_vault_schema_config.py b/skyvault/skyflow/generated/rest/types/v_1_vault_schema_config.py
deleted file mode 100644
index b61e30ea..00000000
--- a/skyvault/skyflow/generated/rest/types/v_1_vault_schema_config.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from .v_1_vault_field_mapping import V1VaultFieldMapping
-
-
-class V1VaultSchemaConfig(UniversalBaseModel):
- """
- Details of the vault that stores additional card details.
- """
-
- id: typing.Optional[str] = pydantic.Field(default=None)
- """
- ID of the vault that stores card details.
- """
-
- table_name: typing.Optional[str] = pydantic.Field(default=None)
- """
- Name of the table that stores card details.
- """
-
- mapping: typing.Optional[V1VaultFieldMapping] = None
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/types/word_character_count.py b/skyvault/skyflow/generated/rest/types/word_character_count.py
deleted file mode 100644
index d2506866..00000000
--- a/skyvault/skyflow/generated/rest/types/word_character_count.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-import pydantic
-import typing_extensions
-from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from ..core.serialization import FieldMetadata
-
-
-class WordCharacterCount(UniversalBaseModel):
- """
- Word and character count of the processed text.
- """
-
- word_count: typing_extensions.Annotated[typing.Optional[int], FieldMetadata(alias="wordCount")] = pydantic.Field(
- default=None
- )
- """
- Number of words in the processed text.
- """
-
- character_count: typing_extensions.Annotated[typing.Optional[int], FieldMetadata(alias="characterCount")] = (
- pydantic.Field(default=None)
- )
- """
- Number of characters in the processed text.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/skyvault/skyflow/generated/rest/version.py b/skyvault/skyflow/generated/rest/version.py
index a93039be..1bf4a7ac 100644
--- a/skyvault/skyflow/generated/rest/version.py
+++ b/skyvault/skyflow/generated/rest/version.py
@@ -1,3 +1,6 @@
from importlib import metadata
-__version__ = metadata.version("skyflow")
+try:
+ __version__ = metadata.version("skyflow")
+except metadata.PackageNotFoundError:
+ __version__ = "0.0.0"
diff --git a/skyvault/skyflow/service_account/__init__.py b/skyvault/skyflow/service_account/__init__.py
index 20d09a8e..1563c2fe 100644
--- a/skyvault/skyflow/service_account/__init__.py
+++ b/skyvault/skyflow/service_account/__init__.py
@@ -1 +1,15 @@
-from ._utils import generate_bearer_token, generate_bearer_token_from_creds, is_expired, generate_signed_data_tokens, generate_signed_data_tokens_from_creds
\ No newline at end of file
+from common.service_account import (
+ generate_bearer_token,
+ generate_bearer_token_from_creds,
+ is_expired,
+ generate_signed_data_tokens,
+ generate_signed_data_tokens_from_creds,
+)
+
+__all__ = [
+ "generate_bearer_token",
+ "generate_bearer_token_from_creds",
+ "is_expired",
+ "generate_signed_data_tokens",
+ "generate_signed_data_tokens_from_creds",
+]
diff --git a/skyvault/skyflow/service_account/client/auth_client.py b/skyvault/skyflow/service_account/client/auth_client.py
index 948e05f3..b43479d7 100644
--- a/skyvault/skyflow/service_account/client/auth_client.py
+++ b/skyvault/skyflow/service_account/client/auth_client.py
@@ -1,4 +1,4 @@
-from skyflow.generated.rest.client import Skyflow
+from skyflow.generated.rest.client import SkyflowAuth
from skyflow.utils.constants import OPTIONAL_TOKEN
class AuthClient:
@@ -7,7 +7,7 @@ def __init__(self, url):
self.__api_client = self.initialize_api_client()
def initialize_api_client(self):
- return Skyflow(base_url=self.__url, token=OPTIONAL_TOKEN)
+ return SkyflowAuth(base_url=self.__url, token=OPTIONAL_TOKEN)
def get_auth_api(self):
return self.__api_client.authentication
\ No newline at end of file
diff --git a/skyvault/skyflow/utils/__init__.py b/skyvault/skyflow/utils/__init__.py
index 664cf65d..3c72b801 100644
--- a/skyvault/skyflow/utils/__init__.py
+++ b/skyvault/skyflow/utils/__init__.py
@@ -2,4 +2,4 @@
from ._skyflow_messages import SkyflowMessages
from ._version import SDK_VERSION
from ._helpers import get_base_url, format_scope, is_valid_url
-from ._utils import get_credentials, get_vault_url, construct_invoke_connection_request, get_metrics, parse_insert_response, handle_exception, parse_update_record_response, parse_delete_response, parse_detokenize_response, parse_tokenize_response, parse_query_response, parse_get_response, parse_invoke_connection_response, validate_api_key, encode_column_values, parse_deidentify_text_response, parse_reidentify_text_response, convert_detected_entity_to_entity_info
+from ._utils import get_credentials, get_vault_url, construct_invoke_connection_request, get_metrics, parse_insert_response, handle_exception, parse_update_record_response, parse_delete_response, parse_detokenize_response, parse_tokenize_response, parse_query_response, parse_get_response, parse_invoke_connection_response, validate_api_key, encode_column_values
diff --git a/skyvault/skyflow/utils/_utils.py b/skyvault/skyflow/utils/_utils.py
index 7ed7bc99..55db46fc 100644
--- a/skyvault/skyflow/utils/_utils.py
+++ b/skyvault/skyflow/utils/_utils.py
@@ -12,13 +12,11 @@
import re
from urllib.parse import quote
from skyflow.error import SkyflowError
-from skyflow.generated.rest import V1UpdateRecordResponse, V1BulkDeleteRecordResponse, \
- V1DetokenizeResponse, V1TokenizeResponse, V1GetQueryResponse, V1BulkGetRecordResponse, \
- DeidentifyStringResponse, ErrorResponse, IdentifyResponse
+from skyflow.generated.rest import UpdateRecordResponse, BulkDeleteRecordResponse, \
+ DetokenizeResponse as GeneratedDetokenizeResponse, TokenizeResponse as GeneratedTokenizeResponse, \
+ GetQueryResponse, BulkGetRecordResponse, ErrorResponse
from skyflow.generated.rest.core.http_response import HttpResponse
from skyflow.utils.logger import log_error_log
-from skyflow.vault.detect import DeidentifyTextResponse, ReidentifyTextResponse
-from skyflow.vault.detect import EntityInfo, TextIndex
from . import SkyflowMessages, SDK_VERSION
from .constants import (PROTOCOL, HttpHeader, ApiKey, ContentType as ContentTypeConstants,
EncodingType, BooleanString, ResponseField, CredentialField, SdkPrefix,
@@ -79,22 +77,6 @@ def to_lowercase_keys(data):
return result
-def convert_detected_entity_to_entity_info(detected_entity):
- return EntityInfo(
- token=detected_entity.token,
- value=detected_entity.value,
- text_index=TextIndex(
- start=detected_entity.location.start_index,
- end=detected_entity.location.end_index
- ),
- processed_index=TextIndex(
- start=detected_entity.location.start_index_processed,
- end=detected_entity.location.end_index_processed
- ),
- entity=detected_entity.entity_type,
- scores=detected_entity.entity_scores
- )
-
def construct_invoke_connection_request(request, connection_url, logger) -> PreparedRequest:
url = parse_path_params(connection_url.rstrip('/'), request.path_params)
@@ -310,7 +292,7 @@ def parse_insert_response(api_response, continue_on_error):
return insert_response
-def parse_update_record_response(api_response: V1UpdateRecordResponse):
+def parse_update_record_response(api_response: UpdateRecordResponse):
update_response = UpdateResponse()
updated_field = dict()
updated_field[ResponseField.SKYFLOW_ID] = api_response.skyflow_id
@@ -321,14 +303,14 @@ def parse_update_record_response(api_response: V1UpdateRecordResponse):
return update_response
-def parse_delete_response(api_response: V1BulkDeleteRecordResponse):
+def parse_delete_response(api_response: BulkDeleteRecordResponse):
delete_response = DeleteResponse()
deleted_ids = api_response.record_id_response
delete_response.deleted_ids = deleted_ids
delete_response.errors = None
return delete_response
-def parse_get_response(api_response: V1BulkGetRecordResponse):
+def parse_get_response(api_response: BulkGetRecordResponse):
get_response = GetResponse()
data = []
for record in api_response.records:
@@ -338,7 +320,7 @@ def parse_get_response(api_response: V1BulkGetRecordResponse):
get_response.data = data
return get_response
-def parse_detokenize_response(api_response: HttpResponse[V1DetokenizeResponse]):
+def parse_detokenize_response(api_response: HttpResponse[GeneratedDetokenizeResponse]):
# Retrieve the headers and data from the API response
api_response_headers = api_response.headers
api_response_data = api_response.data
@@ -370,7 +352,7 @@ def parse_detokenize_response(api_response: HttpResponse[V1DetokenizeResponse]):
return detokenize_response
-def parse_tokenize_response(api_response: V1TokenizeResponse):
+def parse_tokenize_response(api_response: GeneratedTokenizeResponse):
tokenize_response = TokenizeResponse()
tokenized_fields = [{ResponseField.TOKEN: record.token} for record in api_response.records]
@@ -378,7 +360,7 @@ def parse_tokenize_response(api_response: V1TokenizeResponse):
return tokenize_response
-def parse_query_response(api_response: V1GetQueryResponse):
+def parse_query_response(api_response: GetQueryResponse):
query_response = QueryResponse()
fields = []
for record in api_response.records:
@@ -448,18 +430,6 @@ def parse_invoke_connection_response(api_response: requests.Response):
except json.JSONDecodeError:
raise SkyflowError(message, status_code, request_id)
-def parse_deidentify_text_response(api_response: DeidentifyStringResponse):
- entities = [convert_detected_entity_to_entity_info(entity) for entity in api_response.entities]
- return DeidentifyTextResponse(
- processed_text=api_response.processed_text,
- entities=entities,
- word_count=api_response.word_count,
- char_count=api_response.character_count
- )
-
-def parse_reidentify_text_response(api_response: IdentifyResponse):
- return ReidentifyTextResponse(api_response.text)
-
def log_and_reject_error(description, status_code, request_id, http_status=None, grpc_code=None, details=None, logger = None):
raise SkyflowError(description, status_code, request_id, grpc_code, http_status, details)
diff --git a/skyvault/skyflow/utils/enums/__init__.py b/skyvault/skyflow/utils/enums/__init__.py
index af293ce2..38a690b0 100644
--- a/skyvault/skyflow/utils/enums/__init__.py
+++ b/skyvault/skyflow/utils/enums/__init__.py
@@ -6,7 +6,19 @@
from .token_type import TokenType
from .request_method import RequestMethod
from .redaction_type import RedactionType
-from .detect_entities import DetectEntities
from .detect_output_transcriptions import DetectOutputTranscriptions
-from .masking_method import MaskingMethod
-from .token_type import TokenType
\ No newline at end of file
+from ._deidentify_source_type import DeidentifySourceType
+from ._reidentify_source_type import ReidentifySourceType
+from common.utils.enums.detect import (
+ DeidentificationType,
+ DetectRunStatus,
+ EntityType,
+ FileDataFormat,
+ GuardrailsValidation,
+ MaskingMethod,
+ ObjectDeidentificationType,
+ ObjectEntityType,
+ OutputTranscriptionType,
+ PdfProcessingMode,
+ ReturnEntitiesType,
+)
diff --git a/skyvault/skyflow/utils/enums/_deidentify_source_type.py b/skyvault/skyflow/utils/enums/_deidentify_source_type.py
new file mode 100644
index 00000000..28c0e42e
--- /dev/null
+++ b/skyvault/skyflow/utils/enums/_deidentify_source_type.py
@@ -0,0 +1,7 @@
+from enum import Enum
+
+
+class DeidentifySourceType(Enum):
+ BASE64 = "BASE64"
+ SKYFLOW_ID = "SKYFLOW_ID"
+ PRESIGNED_URL = "PRESIGNED_URL"
diff --git a/skyvault/skyflow/utils/enums/_reidentify_source_type.py b/skyvault/skyflow/utils/enums/_reidentify_source_type.py
new file mode 100644
index 00000000..8bce69da
--- /dev/null
+++ b/skyvault/skyflow/utils/enums/_reidentify_source_type.py
@@ -0,0 +1,6 @@
+from enum import Enum
+
+
+class ReidentifySourceType(Enum):
+ BASE64 = "BASE64"
+ PRESIGNED_URL = "PRESIGNED_URL"
diff --git a/skyvault/skyflow/utils/validations/__init__.py b/skyvault/skyflow/utils/validations/__init__.py
index ede551d8..b6ec583a 100644
--- a/skyvault/skyflow/utils/validations/__init__.py
+++ b/skyvault/skyflow/utils/validations/__init__.py
@@ -15,8 +15,4 @@
validate_tokenize_request,
validate_file_upload_request,
validate_invoke_connection_params,
- validate_deidentify_text_request,
- validate_reidentify_text_request,
- validate_deidentify_file_request,
- validate_get_detect_run_request,
)
\ No newline at end of file
diff --git a/skyvault/skyflow/utils/validations/_validations.py b/skyvault/skyflow/utils/validations/_validations.py
index ba2b0f4f..54001e71 100644
--- a/skyvault/skyflow/utils/validations/_validations.py
+++ b/skyvault/skyflow/utils/validations/_validations.py
@@ -9,8 +9,7 @@
validate_token_options as _common_validate_token_options,
)
from skyflow.service_account import is_expired
-from skyflow.utils.enums import RedactionType, TokenMode, DetectEntities, DetectOutputTranscriptions, \
- MaskingMethod
+from skyflow.utils.enums import RedactionType, TokenMode
from skyflow.error import SkyflowError
from skyflow.utils import SkyflowMessages
from skyflow.utils.constants import (
@@ -19,9 +18,6 @@
DeidentifyFileRequestField, RequestOperation, ConfigType, SqlCommand, ConfigField, OptionField, CredentialField, Detect
)
from skyflow.utils.logger import log_info, log_warn, log_error_log
-from skyflow.vault.detect import DeidentifyTextRequest, ReidentifyTextRequest, TokenFormat, Transformations, \
- GetDetectRunRequest, Bleep, DeidentifyFileRequest
-from skyflow.vault.detect._file_input import FileInput
from skyflow.utils._helpers import is_valid_url
valid_connection_config_keys = [
@@ -154,168 +150,6 @@ def validate_update_connection_config(logger, config):
return True
-def validate_file_from_request(file_input: FileInput):
- if file_input is None:
- log_error_log(SkyflowMessages.Error.INVALID_FILE_INPUT.value)
- raise SkyflowError(SkyflowMessages.Error.INVALID_FILE_INPUT.value, invalid_input_error_code)
-
- has_file = hasattr(file_input, FileUploadField.FILE) and file_input.file is not None
- has_file_path = hasattr(file_input, FileUploadField.FILE_PATH) and file_input.file_path is not None
-
- # Must provide exactly one of file or file_path
- if (has_file and has_file_path) or (not has_file and not has_file_path):
- log_error_log(SkyflowMessages.Error.INVALID_DEIDENTIFY_FILE_INPUT.value)
- raise SkyflowError(SkyflowMessages.Error.INVALID_DEIDENTIFY_FILE_INPUT.value, invalid_input_error_code)
-
- if has_file:
- file = file_input.file
- # Validate file object has required attributes
- if not hasattr(file, FileUploadField.NAME) or not isinstance(file.name, str) or not file.name.strip():
- log_error_log(SkyflowMessages.Error.INVALID_FILE_TYPE.value)
- raise SkyflowError(SkyflowMessages.Error.INVALID_FILE_TYPE.value, invalid_input_error_code)
-
- # Validate file name
- file_name, _ = os.path.splitext(os.path.basename(file.name))
- if not file_name or not file_name.strip():
- log_error_log(SkyflowMessages.Error.INVALID_FILE_NAME.value)
- raise SkyflowError(SkyflowMessages.Error.INVALID_FILE_NAME.value, invalid_input_error_code)
-
- elif has_file_path:
- file_path = file_input.file_path
- if not isinstance(file_path, str) or not file_path.strip():
- log_error_log(SkyflowMessages.Error.INVALID_DEIDENTIFY_FILE_PATH.value)
- raise SkyflowError(SkyflowMessages.Error.INVALID_DEIDENTIFY_FILE_PATH.value, invalid_input_error_code)
-
- if not os.path.exists(file_path) or not os.path.isfile(file_path):
- log_error_log(SkyflowMessages.Error.INVALID_DEIDENTIFY_FILE_PATH.value)
- raise SkyflowError(SkyflowMessages.Error.INVALID_DEIDENTIFY_FILE_PATH.value, invalid_input_error_code)
-
-def validate_deidentify_file_request(logger, request: DeidentifyFileRequest):
- if not hasattr(request, FileUploadField.FILE) or request.file is None:
- log_error_log(SkyflowMessages.Error.INVALID_FILE_INPUT.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_FILE_INPUT.value, invalid_input_error_code)
-
- # Validate file input first
- validate_file_from_request(request.file)
-
- # Optional: entities
- if hasattr(request, DeidentifyFileRequestField.ENTITIES) and request.entities is not None:
- if not isinstance(request.entities, list):
- log_error_log(SkyflowMessages.Error.INVALID_DETECT_ENTITIES_TYPE.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_DETECT_ENTITIES_TYPE.value, invalid_input_error_code)
-
- if not all(isinstance(entity, DetectEntities) for entity in request.entities):
- log_error_log(SkyflowMessages.Error.INVALID_DETECT_ENTITIES_TYPE.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_DETECT_ENTITIES_TYPE.value, invalid_input_error_code)
-
- # Optional: allow_regex_list
- if hasattr(request, DeidentifyFileRequestField.ALLOW_REGEX_LIST) and request.allow_regex_list is not None:
- if not isinstance(request.allow_regex_list, list) or not all(isinstance(x, str) for x in request.allow_regex_list):
- log_error_log(SkyflowMessages.Error.INVALID_ALLOW_REGEX_LIST.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_ALLOW_REGEX_LIST.value, invalid_input_error_code)
-
- # Optional: restrict_regex_list
- if hasattr(request, DeidentifyFileRequestField.RESTRICT_REGEX_LIST) and request.restrict_regex_list is not None:
- if not isinstance(request.restrict_regex_list, list) or not all(isinstance(x, str) for x in request.restrict_regex_list):
- log_error_log(SkyflowMessages.Error.INVALID_RESTRICT_REGEX_LIST.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_RESTRICT_REGEX_LIST.value, invalid_input_error_code)
-
- # Optional: token_format
- if request.token_format is not None and not isinstance(request.token_format, TokenFormat):
- log_error_log(SkyflowMessages.Error.INVALID_TOKEN_FORMAT.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_TOKEN_FORMAT.value, invalid_input_error_code)
-
- # Optional: transformations
- if request.transformations is not None and not isinstance(request.transformations, Transformations):
- log_error_log(SkyflowMessages.Error.INVALID_TRANSFORMATIONS.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_TRANSFORMATIONS.value, invalid_input_error_code)
-
- # Optional: output_processed_image
- if hasattr(request, DeidentifyFileRequestField.OUTPUT_PROCESSED_IMAGE) and request.output_processed_image is not None:
- if not isinstance(request.output_processed_image, bool):
- log_error_log(SkyflowMessages.Error.INVALID_OUTPUT_PROCESSED_IMAGE.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_OUTPUT_PROCESSED_IMAGE.value, invalid_input_error_code)
-
- # Optional: output_ocr_text
- if hasattr(request, DeidentifyFileRequestField.OUTPUT_OCR_TEXT) and request.output_ocr_text is not None:
- if not isinstance(request.output_ocr_text, bool):
- log_error_log(SkyflowMessages.Error.INVALID_OUTPUT_OCR_TEXT.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_OUTPUT_OCR_TEXT.value, invalid_input_error_code)
-
- # Optional: masking_method
- if hasattr(request, DeidentifyFileRequestField.MASKING_METHOD) and request.masking_method is not None:
- if not isinstance(request.masking_method, MaskingMethod):
- log_error_log(SkyflowMessages.Error.INVALID_MASKING_METHOD.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_MASKING_METHOD.value, invalid_input_error_code)
-
- # Optional: pixel_density
- if hasattr(request, DeidentifyFileRequestField.PIXEL_DENSITY) and request.pixel_density is not None:
- if not isinstance(request.pixel_density, (int, float)):
- log_error_log(SkyflowMessages.Error.INVALID_PIXEL_DENSITY.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_PIXEL_DENSITY.value, invalid_input_error_code)
-
- # Optional: max_resolution
- if hasattr(request, DeidentifyFileRequestField.MAX_RESOLUTION) and request.max_resolution is not None:
- if not isinstance(request.max_resolution, (int, float)):
- log_error_log(SkyflowMessages.Error.INVALID_MAXIMUM_RESOLUTION.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_MAXIMUM_RESOLUTION.value, invalid_input_error_code)
-
- # Optional: output_processed_audio
- if hasattr(request, DeidentifyFileRequestField.OUTPUT_PROCESSED_AUDIO) and request.output_processed_audio is not None:
- if not isinstance(request.output_processed_audio, bool):
- log_error_log(SkyflowMessages.Error.INVALID_OUTPUT_PROCESSED_AUDIO.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_OUTPUT_PROCESSED_AUDIO.value, invalid_input_error_code)
-
- # Optional: output_transcription
- if hasattr(request, DeidentifyFileRequestField.OUTPUT_TRANSCRIPTION) and request.output_transcription is not None:
- if not isinstance(request.output_transcription, DetectOutputTranscriptions):
- log_error_log(SkyflowMessages.Error.INVALID_OUTPUT_TRANSCRIPTION.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_OUTPUT_TRANSCRIPTION.value, invalid_input_error_code)
-
- # Optional: bleep
- if hasattr(request, DeidentifyFileRequestField.BLEEP) and request.bleep is not None:
- if not isinstance(request.bleep, Bleep):
- log_error_log(SkyflowMessages.Error.INVALID_BLEEP_TYPE.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_BLEEP_TYPE.value, invalid_input_error_code)
-
- # Validate gain
- if request.bleep.gain is not None and not isinstance(request.bleep.gain, (int, float)):
- log_error_log(SkyflowMessages.Error.INVALID_BLEEP_GAIN.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_BLEEP_GAIN.value, invalid_input_error_code)
-
- # Validate frequency
- if request.bleep.frequency is not None and not isinstance(request.bleep.frequency, (int, float)):
- log_error_log(SkyflowMessages.Error.INVALID_BLEEP_FREQUENCY.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_BLEEP_FREQUENCY.value, invalid_input_error_code)
-
- # Validate start_padding
- if request.bleep.start_padding is not None and not isinstance(request.bleep.start_padding, (int, float)):
- log_error_log(SkyflowMessages.Error.INVALID_BLEEP_START_PADDING.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_BLEEP_START_PADDING.value, invalid_input_error_code)
-
- # Validate stop_padding
- if request.bleep.stop_padding is not None and not isinstance(request.bleep.stop_padding, (int, float)):
- log_error_log(SkyflowMessages.Error.INVALID_BLEEP_STOP_PADDING.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_BLEEP_STOP_PADDING.value, invalid_input_error_code)
-
- # Optional: output_directory
- if hasattr(request, DeidentifyFileRequestField.OUTPUT_DIRECTORY) and request.output_directory is not None:
- if not isinstance(request.output_directory, str):
- log_error_log(SkyflowMessages.Error.INVALID_OUTPUT_DIRECTORY_VALUE.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_OUTPUT_DIRECTORY_VALUE.value, invalid_input_error_code)
- if not os.path.isdir(request.output_directory):
- log_error_log(SkyflowMessages.Error.OUTPUT_DIRECTORY_NOT_FOUND.value.format(request.output_directory), logger)
- raise SkyflowError(SkyflowMessages.Error.OUTPUT_DIRECTORY_NOT_FOUND.value.format(request.output_directory), invalid_input_error_code)
-
- # Optional: wait_time
- if hasattr(request, DeidentifyFileRequestField.WAIT_TIME) and request.wait_time is not None:
- if not isinstance(request.wait_time, (int, float)):
- log_error_log(SkyflowMessages.Error.INVALID_WAIT_TIME.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_WAIT_TIME.value, invalid_input_error_code)
- if request.wait_time < 0 or request.wait_time > Detect.WAIT_TIME:
- log_error_log(SkyflowMessages.Error.WAIT_TIME_GREATER_THEN_64.value, logger)
- raise SkyflowError(SkyflowMessages.Error.WAIT_TIME_GREATER_THEN_64.value, invalid_input_error_code)
-
def validate_insert_request(logger, request):
if not isinstance(request.table, str):
log_error_log(SkyflowMessages.ErrorLogs.TABLE_IS_REQUIRED.value.format(RequestOperation.INSERT), logger = logger)
@@ -714,57 +548,3 @@ def validate_invoke_connection_params(logger, query_params, path_params):
except TypeError:
raise SkyflowError(SkyflowMessages.Error.INVALID_QUERY_PARAMS.value, invalid_input_error_code)
-def validate_deidentify_text_request(logger, request: DeidentifyTextRequest):
- if not request.text or not isinstance(request.text, str) or not request.text.strip():
- log_error_log(SkyflowMessages.Error.INVALID_TEXT_IN_DEIDENTIFY.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_TEXT_IN_DEIDENTIFY.value, invalid_input_error_code)
-
- # Validate entities if present
- if request.entities is not None and not isinstance(request.entities, list):
- log_error_log(SkyflowMessages.Error.INVALID_ENTITIES_IN_DEIDENTIFY.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_ENTITIES_IN_DEIDENTIFY.value, invalid_input_error_code)
-
- # Validate allowed_regex_list if present
- if request.allow_regex_list is not None and not isinstance(request.allow_regex_list, list):
- log_error_log(SkyflowMessages.Error.INVALID_ALLOW_REGEX_LIST.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_ALLOW_REGEX_LIST.value, invalid_input_error_code)
-
- # Validate restricted_regex_list if present
- if request.restrict_regex_list is not None and not isinstance(request.restrict_regex_list, list):
- log_error_log(SkyflowMessages.Error.INVALID_RESTRICT_REGEX_LIST.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_RESTRICT_REGEX_LIST.value, invalid_input_error_code)
-
- # Validate token_format if present
- if request.token_format is not None and not isinstance(request.token_format, TokenFormat):
- log_error_log(SkyflowMessages.Error.INVALID_TOKEN_FORMAT.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_TOKEN_FORMAT.value, invalid_input_error_code)
-
- # Validate transformations if present
- if request.transformations is not None and not isinstance(request.transformations, Transformations):
- log_error_log(SkyflowMessages.Error.INVALID_TRANSFORMATIONS.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_TRANSFORMATIONS.value, invalid_input_error_code)
-
-def validate_reidentify_text_request(logger, request: ReidentifyTextRequest):
- if not request.text or not isinstance(request.text, str) or not request.text.strip():
- log_error_log(SkyflowMessages.Error.INVALID_TEXT_IN_REIDENTIFY.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_TEXT_IN_REIDENTIFY.value, invalid_input_error_code)
-
- # Validate redacted_entities if present
- if request.redacted_entities is not None and not isinstance(request.redacted_entities, list):
- log_error_log(SkyflowMessages.Error.INVALID_REDACTED_ENTITIES_IN_REIDENTIFY.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_REDACTED_ENTITIES_IN_REIDENTIFY.value, invalid_input_error_code)
-
- # Validate masked_entities if present
- if request.masked_entities is not None and not isinstance(request.masked_entities, list):
- log_error_log(SkyflowMessages.Error.INVALID_MASKED_ENTITIES_IN_REIDENTIFY.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_MASKED_ENTITIES_IN_REIDENTIFY.value, invalid_input_error_code)
-
- # Validate plain_text_entities if present
- if request.plain_text_entities is not None and not isinstance(request.plain_text_entities, list):
- log_error_log(SkyflowMessages.Error.INVALID_PLAIN_TEXT_ENTITIES_IN_REIDENTIFY.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_PLAIN_TEXT_ENTITIES_IN_REIDENTIFY.value, invalid_input_error_code)
-
-def validate_get_detect_run_request(logger, request: GetDetectRunRequest):
- if request.run_id is None or not isinstance(request.run_id, str) or not request.run_id.strip():
- log_error_log(SkyflowMessages.ErrorLogs.INVALID_RUN_ID.value, logger)
- raise SkyflowError(SkyflowMessages.Error.INVALID_RUN_ID.value, invalid_input_error_code)
diff --git a/skyvault/skyflow/vault/client/client.py b/skyvault/skyflow/vault/client/client.py
index 7ddb8996..d8071042 100644
--- a/skyvault/skyflow/vault/client/client.py
+++ b/skyvault/skyflow/vault/client/client.py
@@ -1,6 +1,8 @@
from common.utils import get_vault_url
from common.vault.base_vault_client import BaseVaultClient
-from skyflow.generated.rest.client import Skyflow
+from common.generated.rest.client import SkyflowAuth as DetectSkyflowAuth
+from skyflow.generated.rest.client import SkyflowAuth
+from skyflow.utils._utils import get_metrics
class VaultClient(BaseVaultClient):
@@ -9,7 +11,8 @@ def resolve_vault_url(self, cluster_id, env, vault_id, logger=None):
def initialize_api_client(self, vault_url, bearer_token):
token_provider = lambda: self._bearer_token if self._bearer_token is not None else bearer_token # noqa: E731
- self._api_client = Skyflow(base_url=vault_url, token=token_provider)
+ self._api_client = SkyflowAuth(base_url=vault_url, token=token_provider)
+ self._detect_api_client = DetectSkyflowAuth(base_url=vault_url, token=token_provider)
def get_records_api(self):
return self._api_client.records
@@ -20,8 +23,25 @@ def get_tokens_api(self):
def get_query_api(self):
return self._api_client.query
- def get_detect_text_api(self):
- return self._api_client.strings
-
- def get_detect_file_api(self):
+ def get_files_api(self):
return self._api_client.files
+
+ def get_strings_v2_api(self):
+ return self._detect_api_client.strings_v2
+
+ def get_files_v2_api(self):
+ return self._detect_api_client.files_v2
+
+ def get_guardrails_v2_api(self):
+ return self._detect_api_client.guardrails_v2
+
+ def get_deidentify_source_type(self):
+ from skyflow.utils.enums import DeidentifySourceType
+ return DeidentifySourceType
+
+ def get_reidentify_source_type(self):
+ from skyflow.utils.enums import ReidentifySourceType
+ return ReidentifySourceType
+
+ def get_sdk_metrics(self):
+ return get_metrics()
diff --git a/skyvault/skyflow/vault/controller/__init__.py b/skyvault/skyflow/vault/controller/__init__.py
index 2840034e..269110ec 100644
--- a/skyvault/skyflow/vault/controller/__init__.py
+++ b/skyvault/skyflow/vault/controller/__init__.py
@@ -1,6 +1,5 @@
from ._vault import VaultController
from ._connections import Connection
-from ._detect import Detect
# Public backward-compatible name -- existing consumers do `from skyflow.vault.controller import
# Vault`; VaultController is the canonical internal name (extends common.vault.base_vault_controller's
diff --git a/skyvault/skyflow/vault/controller/_detect.py b/skyvault/skyflow/vault/controller/_detect.py
deleted file mode 100644
index 754e7799..00000000
--- a/skyvault/skyflow/vault/controller/_detect.py
+++ /dev/null
@@ -1,479 +0,0 @@
-import io
-import json
-import os
-import base64
-import time
-from skyflow.generated.rest import FileDataDeidentifyText, FileDataDeidentifyPdf, FileDataDeidentifyPresentation, \
- FileDataDeidentifySpreadsheet, FileDataDeidentifyDocument, FileDataDeidentifyStructuredText, FileData, \
- FileDataDeidentifyImage, Format, FileDataDeidentifyAudio, WordCharacterCount, DetectRunsResponse
-from skyflow.utils._skyflow_messages import SkyflowMessages
-from skyflow.utils._utils import get_attribute, get_metrics, handle_exception, parse_deidentify_text_response, parse_reidentify_text_response
-from skyflow.utils.constants import (SKY_META_DATA_HEADER, DetectStatus, FileExtension,
- FileProcessing, EncodingType, DeidentifyField, DeidentifyFileRequestField, FileUploadField, OptionField, Detect as DetectConstants)
-from skyflow.utils.logger import log_info, log_error_log
-from skyflow.utils.validations import validate_deidentify_file_request, validate_get_detect_run_request
-from skyflow.utils.validations._validations import validate_deidentify_text_request, validate_reidentify_text_request
-from typing import Dict, Any
-from skyflow.vault.detect import DeidentifyTextRequest, DeidentifyTextResponse, ReidentifyTextRequest, \
- ReidentifyTextResponse, DeidentifyFileRequest, DeidentifyFileResponse, GetDetectRunRequest
-
-class Detect:
- def __init__(self, vault_client):
- self.__vault_client = vault_client
-
- def __initialize(self):
- self.__vault_client.initialize_client_configuration()
-
- def __get_headers(self):
- headers = {
- SKY_META_DATA_HEADER: json.dumps(get_metrics())
- }
- return headers
-
- def __build_deidentify_text_body(self, request: DeidentifyTextRequest) -> Dict[str, Any]:
- deidentify_text_body = {}
- parsed_entity_types = request.entities
-
- deidentify_text_body[DeidentifyField.TEXT] = request.text
- deidentify_text_body[DeidentifyField.ENTITY_TYPES] = parsed_entity_types
- deidentify_text_body[DeidentifyField.TOKEN_TYPE] = self.__get_token_format(request)
- deidentify_text_body[DeidentifyField.ALLOW_REGEX] = request.allow_regex_list
- deidentify_text_body[DeidentifyField.RESTRICT_REGEX] = request.restrict_regex_list
- deidentify_text_body[DeidentifyField.TRANSFORMATIONS] = self.__get_transformations(request)
-
- return deidentify_text_body
-
- def __build_reidentify_text_body(self, request: ReidentifyTextRequest) -> Dict[str, Any]:
- parsed_format = Format(
- redacted=request.redacted_entities,
- masked=request.masked_entities,
- plaintext=request.plain_text_entities
- )
- reidentify_text_body = {}
- reidentify_text_body[DeidentifyField.TEXT] = request.text
- reidentify_text_body[DeidentifyField.FORMAT] = parsed_format
- return reidentify_text_body
-
- def _get_file_extension(self, filename: str):
- return filename.split('.')[-1].lower() if '.' in filename else ''
-
- def __poll_for_processed_file(self, run_id, max_wait_time=None):
- max_wait_time = DetectConstants.WAIT_TIME if max_wait_time is None else max_wait_time
- files_api = self.__vault_client.get_detect_file_api().with_raw_response
- current_wait_time = 1 # Start with 1 second
- try:
- while True:
- response = files_api.get_run(run_id, vault_id=self.__vault_client.get_vault_id(), request_options={'additional_headers': self.__get_headers()}).data
- status = response.status
- if status == DetectStatus.IN_PROGRESS:
- if current_wait_time >= max_wait_time:
- return DeidentifyFileResponse(run_id=run_id, status=DetectStatus.IN_PROGRESS)
- else:
- next_wait_time = current_wait_time * 2
- if next_wait_time >= max_wait_time:
- wait_time = max_wait_time - current_wait_time
- current_wait_time = max_wait_time
- else:
- wait_time = next_wait_time
- current_wait_time = next_wait_time
- time.sleep(wait_time)
- elif status == DetectStatus.SUCCESS or status == DetectStatus.FAILED:
- return response
- except Exception as e:
- handle_exception(e, self.__vault_client.get_logger())
-
- def __save_deidentify_file_response_output(self, response: DetectRunsResponse, output_directory: str, original_file_name: str, name_without_ext: str):
- if not response or not hasattr(response, DeidentifyField.OUTPUT) or not response.output or not output_directory:
- return
-
- if not os.path.exists(output_directory):
- return
-
- deidentify_file_prefix = FileProcessing.PROCESSED_PREFIX
- output_list = response.output
-
- base_original_filename = os.path.basename(original_file_name)
- base_name_without_ext = os.path.splitext(base_original_filename)[0]
- real_output_dir = os.path.realpath(output_directory)
-
- for idx, output in enumerate(output_list):
- try:
- processed_file = get_attribute(output, DeidentifyField.PROCESSED_FILE_RESPONSE_KEY, DeidentifyField.PROCESSED_FILE)
- processed_file_type = get_attribute(output, DeidentifyField.PROCESSED_FILE_TYPE_RESPONSE_KEY, DeidentifyField.PROCESSED_FILE_TYPE)
- processed_file_extension = get_attribute(output, DeidentifyField.PROCESSED_FILE_EXTENSION_RESPONSE_KEY, DeidentifyField.PROCESSED_FILE_EXTENSION)
-
- if not processed_file:
- continue
-
- decoded_data = base64.b64decode(processed_file)
-
- # Sanitize extension from API response to prevent path traversal (CWE-22).
- # Avoid os.path.basename here to keep basename mock-free in tests.
- safe_ext = None
- if processed_file_extension:
- raw_ext = str(processed_file_extension).replace('\\', '/').split('/')[-1].lstrip('.')
- safe_ext = ''.join(c for c in raw_ext if c.isalnum() or c in ('-', '_')) or 'bin'
-
- if idx == 0 or processed_file_type == DeidentifyField.REDACTED_FILE:
- output_file_name = os.path.join(output_directory, deidentify_file_prefix + base_original_filename)
- if safe_ext:
- output_file_name = os.path.join(output_directory, f"{deidentify_file_prefix}{base_name_without_ext}.{safe_ext}")
- else:
- output_file_name = os.path.join(output_directory, f"{deidentify_file_prefix}{base_name_without_ext}.{safe_ext or 'bin'}")
-
- if not os.path.realpath(output_file_name).startswith(real_output_dir + os.sep):
- log_error_log(SkyflowMessages.ErrorLogs.SAVING_DEIDENTIFY_FILE_FAILED.value, self.__vault_client.get_logger())
- continue
-
- with open(output_file_name, 'wb') as f:
- f.write(decoded_data)
- except Exception as e:
- log_error_log(SkyflowMessages.ErrorLogs.SAVING_DEIDENTIFY_FILE_FAILED.value, self.__vault_client.get_logger())
- handle_exception(e, self.__vault_client.get_logger())
-
- def __parse_deidentify_file_response(self, data, run_id=None, status=None):
- output = getattr(data, DeidentifyField.OUTPUT, [])
- status_val = getattr(data, DeidentifyField.STATUS, None) or status
- run_id_val = getattr(data, DeidentifyField.RUN_ID, None) or run_id
-
- word_count = None
- char_count = None
-
- word_character_count = getattr(data, DeidentifyField.WORD_CHARACTER_COUNT, None)
- if word_character_count and isinstance(word_character_count, WordCharacterCount):
- word_count = getattr(word_character_count, DeidentifyField.WORD_COUNT, None)
- char_count = getattr(word_character_count, DeidentifyField.CHARACTER_COUNT, None)
-
- size = getattr(data, DeidentifyField.SIZE, None)
-
- size = float(size) if size is not None else None
-
- duration = getattr(data, DeidentifyField.DURATION, None)
- pages = getattr(data, DeidentifyField.PAGES, None)
- slides = getattr(data, DeidentifyField.SLIDES, None)
-
- def output_to_dict_list(output):
- result = []
- for o in output:
- if isinstance(o, dict):
- result.append({
- DeidentifyField.FILE: o.get(DeidentifyField.PROCESSED_FILE),
- DeidentifyField.TYPE: o.get(DeidentifyField.PROCESSED_FILE_TYPE),
- DeidentifyField.EXTENSION: o.get(DeidentifyField.PROCESSED_FILE_EXTENSION)
- })
- else:
- result.append({
- DeidentifyField.FILE: getattr(o, DeidentifyField.PROCESSED_FILE, None),
- DeidentifyField.TYPE: getattr(o, DeidentifyField.PROCESSED_FILE_TYPE, None),
- DeidentifyField.EXTENSION: getattr(o, DeidentifyField.PROCESSED_FILE_EXTENSION, None)
- })
- return result
-
- output_list = output_to_dict_list(output)
- first_output = output_list[0] if output_list else {}
-
- entities = [o for o in output_list if o.get(DeidentifyField.TYPE) == FileProcessing.ENTITIES]
-
- base64_string = first_output.get(DeidentifyField.FILE, None)
- extension = first_output.get(DeidentifyField.EXTENSION, None)
-
- if base64_string is not None:
- file_bytes = base64.b64decode(base64_string)
- file_obj = io.BytesIO(file_bytes)
- file_obj.name = f"{FileProcessing.DEIDENTIFIED_PREFIX}{extension}" if extension else DeidentifyField.PROCESSED_FILE
- else:
- file_obj = None
-
- return DeidentifyFileResponse(
- file_base64=base64_string,
- file=file_obj,
- type=first_output.get(DeidentifyField.TYPE, None),
- extension=extension,
- word_count=word_count,
- char_count=char_count,
- size_in_kb=size,
- duration_in_seconds=duration,
- page_count=pages,
- slide_count=slides,
- entities=entities,
- run_id=run_id_val,
- status=status_val,
- )
-
- def __get_token_format(self, request):
- if not hasattr(request, DeidentifyField.TOKEN_FORMAT) or request.token_format is None:
- return None
- return {
- DeidentifyField.DEFAULT: getattr(request.token_format, DeidentifyField.DEFAULT, None),
- DeidentifyField.ENTITY_UNQ_COUNTER: getattr(request.token_format, DeidentifyField.ENTITY_UNIQUE_COUNTER, None),
- DeidentifyField.ENTITY_ONLY: getattr(request.token_format, DeidentifyField.ENTITY_ONLY, None),
- DeidentifyField.VAULT_TOKEN: getattr(request.token_format, DeidentifyField.VAULT_TOKEN, None)
- }
-
- def __get_transformations(self, request):
- if not hasattr(request, DeidentifyField.TRANSFORMATIONS) or request.transformations is None:
- return None
- shift_dates = getattr(request.transformations, DeidentifyField.SHIFT_DATES, None)
- if shift_dates is None:
- return None
- return {
- DeidentifyField.SHIFT_DATES: {
- DeidentifyField.MAX_DAYS: getattr(shift_dates, DeidentifyField.MAX, None),
- DeidentifyField.MIN_DAYS: getattr(shift_dates, DeidentifyField.MIN, None),
- DeidentifyField.ENTITY_TYPES: getattr(shift_dates, DeidentifyField.ENTITIES, None)
- }
- }
-
- def deidentify_text(self, request: DeidentifyTextRequest) -> DeidentifyTextResponse:
- log_info(SkyflowMessages.Info.VALIDATING_DEIDENTIFY_TEXT_INPUT.value, self.__vault_client.get_logger())
- validate_deidentify_text_request(self.__vault_client.get_logger(), request)
- log_info(SkyflowMessages.Info.DEIDENTIFY_TEXT_REQUEST_RESOLVED.value, self.__vault_client.get_logger())
- self.__initialize()
- detect_api = self.__vault_client.get_detect_text_api()
- deidentify_text_body = self.__build_deidentify_text_body(request)
-
- try:
- log_info(SkyflowMessages.Info.DEIDENTIFY_TEXT_TRIGGERED.value, self.__vault_client.get_logger())
- api_response = detect_api.deidentify_string(
- vault_id=self.__vault_client.get_vault_id(),
- text=deidentify_text_body[DeidentifyField.TEXT],
- entity_types=deidentify_text_body[DeidentifyField.ENTITY_TYPES],
- allow_regex=deidentify_text_body[DeidentifyField.ALLOW_REGEX],
- restrict_regex=deidentify_text_body[DeidentifyField.RESTRICT_REGEX],
- token_type=deidentify_text_body[DeidentifyField.TOKEN_TYPE],
- transformations=deidentify_text_body[DeidentifyField.TRANSFORMATIONS],
- request_options={'additional_headers': self.__get_headers()}
- )
- deidentify_text_response = parse_deidentify_text_response(api_response)
- log_info(SkyflowMessages.Info.DEIDENTIFY_TEXT_SUCCESS.value, self.__vault_client.get_logger())
- return deidentify_text_response
-
- except Exception as e:
- log_error_log(SkyflowMessages.ErrorLogs.DEIDENTIFY_TEXT_REQUEST_REJECTED.value, self.__vault_client.get_logger())
- handle_exception(e, self.__vault_client.get_logger())
-
- def reidentify_text(self, request: ReidentifyTextRequest) -> ReidentifyTextResponse:
- log_info(SkyflowMessages.Info.VALIDATING_REIDENTIFY_TEXT_INPUT.value, self.__vault_client.get_logger())
- validate_reidentify_text_request(self.__vault_client.get_logger(), request)
- log_info(SkyflowMessages.Info.REIDENTIFY_TEXT_REQUEST_RESOLVED.value, self.__vault_client.get_logger())
- self.__initialize()
- detect_api = self.__vault_client.get_detect_text_api()
- reidentify_text_body = self.__build_reidentify_text_body(request)
-
- try:
- log_info(SkyflowMessages.Info.REIDENTIFY_TEXT_TRIGGERED.value, self.__vault_client.get_logger())
- api_response = detect_api.reidentify_string(
- vault_id=self.__vault_client.get_vault_id(),
- text=reidentify_text_body[DeidentifyField.TEXT],
- format=reidentify_text_body[DeidentifyField.FORMAT],
- request_options={'additional_headers': self.__get_headers()}
- )
- reidentify_text_response = parse_reidentify_text_response(api_response)
- log_info(SkyflowMessages.Info.REIDENTIFY_TEXT_SUCCESS.value, self.__vault_client.get_logger())
- return reidentify_text_response
-
- except Exception as e:
- log_error_log(SkyflowMessages.ErrorLogs.REIDENTIFY_TEXT_REQUEST_REJECTED.value, self.__vault_client.get_logger())
- handle_exception(e, self.__vault_client.get_logger())
-
- def __get_file_from_request(self, request: DeidentifyFileRequest):
- file_input = request.file
-
- if hasattr(file_input, FileUploadField.FILE) and file_input.file is not None:
- return file_input.file
-
- if hasattr(file_input, FileUploadField.FILE_PATH) and file_input.file_path is not None:
- with open(file_input.file_path, 'rb') as f:
- content = f.read()
- bio = io.BytesIO(content)
- bio.name = file_input.file_path
- return bio
-
- def deidentify_file(self, request: DeidentifyFileRequest):
- log_info(SkyflowMessages.Info.DETECT_FILE_TRIGGERED.value, self.__vault_client.get_logger())
- validate_deidentify_file_request(self.__vault_client.get_logger(), request)
- self.__initialize()
- files_api = self.__vault_client.get_detect_file_api().with_raw_response
- file_obj = self.__get_file_from_request(request)
- file_name = getattr(file_obj, FileUploadField.NAME, None)
- file_extension = self._get_file_extension(file_name) if file_name else None
- file_content = file_obj.read()
- base64_string = base64.b64encode(file_content).decode(EncodingType.UTF_8)
-
- try:
- if file_extension == FileExtension.TXT:
- req_file = FileDataDeidentifyText(base_64=base64_string, data_format=FileExtension.TXT)
- api_call = files_api.deidentify_text
- api_kwargs = {
- OptionField.VAULT_ID: self.__vault_client.get_vault_id(),
- DeidentifyField.FILE: req_file,
- DeidentifyField.ENTITY_TYPES: request.entities,
- DeidentifyField.TOKEN_TYPE: self.__get_token_format(request),
- DeidentifyField.ALLOW_REGEX: request.allow_regex_list,
- DeidentifyField.RESTRICT_REGEX: request.restrict_regex_list,
- DeidentifyField.TRANSFORMATIONS: self.__get_transformations(request),
- DeidentifyField.REQUEST_OPTIONS: {'additional_headers': self.__get_headers()}
- }
-
- elif file_extension in [FileExtension.MP3, FileExtension.WAV]:
- req_file = FileDataDeidentifyAudio(base_64=base64_string, data_format=file_extension)
- api_call = files_api.deidentify_audio
- bleep = request.bleep
- api_kwargs = {
- OptionField.VAULT_ID: self.__vault_client.get_vault_id(),
- DeidentifyField.FILE: req_file,
- DeidentifyField.ENTITY_TYPES: request.entities,
- DeidentifyField.TOKEN_TYPE: self.__get_token_format(request),
- DeidentifyField.ALLOW_REGEX: request.allow_regex_list,
- DeidentifyField.RESTRICT_REGEX: request.restrict_regex_list,
- DeidentifyField.TRANSFORMATIONS: self.__get_transformations(request),
- DeidentifyFileRequestField.OUTPUT_TRANSCRIPTION: getattr(request, DeidentifyFileRequestField.OUTPUT_TRANSCRIPTION, None),
- DeidentifyFileRequestField.OUTPUT_PROCESSED_AUDIO: getattr(request, DeidentifyFileRequestField.OUTPUT_PROCESSED_AUDIO, None),
- DeidentifyField.BLEEP_GAIN: bleep.gain if bleep is not None else None,
- DeidentifyField.BLEEP_FREQUENCY: bleep.frequency if bleep is not None else None,
- DeidentifyField.BLEEP_START_PADDING: bleep.start_padding if bleep is not None else None,
- DeidentifyField.BLEEP_STOP_PADDING: bleep.stop_padding if bleep is not None else None,
- DeidentifyField.REQUEST_OPTIONS: {'additional_headers': self.__get_headers()}
- }
-
- elif file_extension == FileExtension.PDF:
- req_file = FileDataDeidentifyPdf(base_64=base64_string)
- api_call = files_api.deidentify_pdf
- api_kwargs = {
- OptionField.VAULT_ID: self.__vault_client.get_vault_id(),
- DeidentifyField.FILE: req_file,
- DeidentifyField.ENTITY_TYPES: request.entities,
- DeidentifyField.TOKEN_TYPE: self.__get_token_format(request),
- DeidentifyField.ALLOW_REGEX: request.allow_regex_list,
- DeidentifyField.RESTRICT_REGEX: request.restrict_regex_list,
- DeidentifyFileRequestField.MAX_RESOLUTION: getattr(request, DeidentifyFileRequestField.MAX_RESOLUTION, None),
- DeidentifyFileRequestField.DENSITY: getattr(request, DeidentifyFileRequestField.PIXEL_DENSITY, None),
- DeidentifyField.REQUEST_OPTIONS: {'additional_headers': self.__get_headers()}
- }
-
- elif file_extension in [FileExtension.JPEG, FileExtension.JPG, FileExtension.PNG, FileExtension.BMP, FileExtension.TIF, FileExtension.TIFF]:
- req_file = FileDataDeidentifyImage(base_64=base64_string, data_format=file_extension)
- api_call = files_api.deidentify_image
- api_kwargs = {
- OptionField.VAULT_ID: self.__vault_client.get_vault_id(),
- DeidentifyField.FILE: req_file,
- DeidentifyField.ENTITY_TYPES: request.entities,
- DeidentifyField.TOKEN_TYPE: self.__get_token_format(request),
- DeidentifyField.ALLOW_REGEX: request.allow_regex_list,
- DeidentifyField.RESTRICT_REGEX: request.restrict_regex_list,
- DeidentifyFileRequestField.MASKING_METHOD: getattr(request, DeidentifyFileRequestField.MASKING_METHOD, None),
- DeidentifyFileRequestField.OUTPUT_OCR_TEXT: getattr(request, DeidentifyFileRequestField.OUTPUT_OCR_TEXT, None),
- DeidentifyFileRequestField.OUTPUT_PROCESSED_IMAGE: getattr(request, DeidentifyFileRequestField.OUTPUT_PROCESSED_IMAGE, None),
- DeidentifyField.REQUEST_OPTIONS: {'additional_headers': self.__get_headers()}
- }
-
- elif file_extension in [FileExtension.PPT, FileExtension.PPTX]:
- req_file = FileDataDeidentifyPresentation(base_64=base64_string, data_format=file_extension)
- api_call = files_api.deidentify_presentation
- api_kwargs = {
- OptionField.VAULT_ID: self.__vault_client.get_vault_id(),
- DeidentifyField.FILE: req_file,
- DeidentifyField.ENTITY_TYPES: request.entities,
- DeidentifyField.TOKEN_TYPE: self.__get_token_format(request),
- DeidentifyField.ALLOW_REGEX: request.allow_regex_list,
- DeidentifyField.RESTRICT_REGEX: request.restrict_regex_list,
- DeidentifyField.REQUEST_OPTIONS: {'additional_headers': self.__get_headers()}
- }
-
- elif file_extension in [FileExtension.CSV, FileExtension.XLS, FileExtension.XLSX]:
- req_file = FileDataDeidentifySpreadsheet(base_64=base64_string, data_format=file_extension)
- api_call = files_api.deidentify_spreadsheet
- api_kwargs = {
- OptionField.VAULT_ID: self.__vault_client.get_vault_id(),
- DeidentifyField.FILE: req_file,
- DeidentifyField.ENTITY_TYPES: request.entities,
- DeidentifyField.TOKEN_TYPE: self.__get_token_format(request),
- DeidentifyField.ALLOW_REGEX: request.allow_regex_list,
- DeidentifyField.RESTRICT_REGEX: request.restrict_regex_list,
- DeidentifyField.REQUEST_OPTIONS: {'additional_headers': self.__get_headers()}
- }
-
- elif file_extension in [FileExtension.DOC, FileExtension.DOCX]:
- req_file = FileDataDeidentifyDocument(base_64=base64_string, data_format=file_extension)
- api_call = files_api.deidentify_document
- api_kwargs = {
- OptionField.VAULT_ID: self.__vault_client.get_vault_id(),
- DeidentifyField.FILE: req_file,
- DeidentifyField.ENTITY_TYPES: request.entities,
- DeidentifyField.TOKEN_TYPE: self.__get_token_format(request),
- DeidentifyField.ALLOW_REGEX: request.allow_regex_list,
- DeidentifyField.RESTRICT_REGEX: request.restrict_regex_list,
- DeidentifyField.REQUEST_OPTIONS: {'additional_headers': self.__get_headers()}
- }
-
- elif file_extension in [FileExtension.JSON, FileExtension.XML]:
- req_file = FileDataDeidentifyStructuredText(base_64=base64_string, data_format=file_extension)
- api_call = files_api.deidentify_structured_text
- api_kwargs = {
- OptionField.VAULT_ID: self.__vault_client.get_vault_id(),
- DeidentifyField.FILE: req_file,
- DeidentifyField.ENTITY_TYPES: request.entities,
- DeidentifyField.TOKEN_TYPE: self.__get_token_format(request),
- DeidentifyField.ALLOW_REGEX: request.allow_regex_list,
- DeidentifyField.RESTRICT_REGEX: request.restrict_regex_list,
- DeidentifyField.TRANSFORMATIONS: self.__get_transformations(request),
- DeidentifyField.REQUEST_OPTIONS: {'additional_headers': self.__get_headers()}
- }
-
- else:
- req_file = FileData(base_64=base64_string, data_format=file_extension)
- api_call = files_api.deidentify_file
- api_kwargs = {
- OptionField.VAULT_ID: self.__vault_client.get_vault_id(),
- DeidentifyField.FILE: req_file,
- DeidentifyField.ENTITY_TYPES: request.entities,
- DeidentifyField.TOKEN_TYPE: self.__get_token_format(request),
- DeidentifyField.ALLOW_REGEX: request.allow_regex_list,
- DeidentifyField.RESTRICT_REGEX: request.restrict_regex_list,
- DeidentifyField.TRANSFORMATIONS: self.__get_transformations(request),
- DeidentifyField.REQUEST_OPTIONS: {'additional_headers': self.__get_headers()}
- }
-
- log_info(SkyflowMessages.Info.DETECT_FILE_REQUEST_RESOLVED.value, self.__vault_client.get_logger())
- api_response = api_call(**api_kwargs)
-
- run_id = getattr(api_response.data, DeidentifyField.RUN_ID, None)
-
- processed_response = self.__poll_for_processed_file(run_id, request.wait_time)
- if request.output_directory and processed_response.status == DetectStatus.SUCCESS and file_name:
- name_without_ext, _ = os.path.splitext(file_name)
- self.__save_deidentify_file_response_output(processed_response, request.output_directory, file_name, name_without_ext)
-
- parsed_response = self.__parse_deidentify_file_response(processed_response, run_id)
- log_info(SkyflowMessages.Info.DETECT_FILE_SUCCESS.value, self.__vault_client.get_logger())
- return parsed_response
-
- except Exception as e:
- log_error_log(SkyflowMessages.ErrorLogs.DETECT_FILE_REQUEST_REJECTED.value,
- self.__vault_client.get_logger())
- handle_exception(e, self.__vault_client.get_logger())
-
- def get_detect_run(self, request: GetDetectRunRequest):
- log_info(SkyflowMessages.Info.GET_DETECT_RUN_TRIGGERED.value,self.__vault_client.get_logger())
- log_info(SkyflowMessages.Info.VALIDATING_GET_DETECT_RUN_INPUT.value, self.__vault_client.get_logger())
- validate_get_detect_run_request(self.__vault_client.get_logger(), request)
- self.__initialize()
-
- files_api = self.__vault_client.get_detect_file_api().with_raw_response
- run_id = request.run_id
- try:
- response = files_api.get_run(
- run_id,
- vault_id=self.__vault_client.get_vault_id(),
- request_options={'additional_headers': self.__get_headers()}
- )
- if response.data.status == DetectStatus.IN_PROGRESS:
- parsed_response = DeidentifyFileResponse(run_id=run_id, status=DetectStatus.IN_PROGRESS)
- else:
- parsed_response = self.__parse_deidentify_file_response(response.data, run_id, response.data.status)
- log_info(SkyflowMessages.Info.GET_DETECT_RUN_SUCCESS.value,self.__vault_client.get_logger())
- return parsed_response
- except Exception as e:
- log_error_log(SkyflowMessages.ErrorLogs.DETECT_FILE_REQUEST_REJECTED.value,
- self.__vault_client.get_logger())
- handle_exception(e, self.__vault_client.get_logger())
\ No newline at end of file
diff --git a/skyvault/skyflow/vault/controller/_vault.py b/skyvault/skyflow/vault/controller/_vault.py
index 16e6aeac..2689dd62 100644
--- a/skyvault/skyflow/vault/controller/_vault.py
+++ b/skyvault/skyflow/vault/controller/_vault.py
@@ -3,8 +3,8 @@
import os
from typing import Optional
from common.vault.base_vault_controller import BaseVaultController
-from skyflow.generated.rest import V1FieldRecords, V1BatchRecord, V1TokenizeRecordRequest, \
- V1DetokenizeRecordRequest
+from skyflow.generated.rest import FieldRecords, BatchRecord, TokenizeRecordRequest, \
+ DetokenizeRecordRequest
from skyflow.generated.rest.core.file import File
from skyflow.utils import SkyflowMessages, parse_insert_response, \
handle_exception, parse_update_record_response, parse_delete_response, parse_detokenize_response, \
@@ -29,12 +29,12 @@ def __initialize(self):
def __build_bulk_field_records(self, values, tokens=None):
if tokens is None:
- return [V1FieldRecords(fields=record) for record in values]
+ return [FieldRecords(fields=record) for record in values]
else:
bulk_record_list = []
for i, value in enumerate(values):
token = tokens[i] if tokens is not None and i < len(tokens) else None
- bulk_record = V1FieldRecords(
+ bulk_record = FieldRecords(
fields=value,
tokens=token
)
@@ -45,7 +45,7 @@ def __build_batch_field_records(self, values, tokens, table_name, return_tokens,
batch_record_list = []
for i, value in enumerate(values):
token = tokens[i] if tokens is not None and i < len(tokens) else None
- batch_record = V1BatchRecord(
+ batch_record = BatchRecord(
fields=value,
table_name=table_name,
method=RequestMethod.POST.value,
@@ -107,11 +107,11 @@ def insert(self, request: InsertRequest) -> InsertResponse:
try:
log_info(SkyflowMessages.Info.INSERT_TRIGGERED.value, self.__vault_client.get_logger())
if request.continue_on_error:
- api_response = records_api.record_service_batch_operation(self.__vault_client.get_vault_id(),
- records=insert_body, continue_on_error=request.continue_on_error, byot=request.token_mode.value, request_options={'additional_headers': self.__get_headers()})
+ api_response = records_api.batch_operation(self.__vault_client.get_vault_id(),
+ records=insert_body, continue_on_error=request.continue_on_error, request_options={'additional_headers': self.__get_headers()})
else:
- api_response = records_api.record_service_insert_record(self.__vault_client.get_vault_id(),
+ api_response = records_api.insert_records(self.__vault_client.get_vault_id(),
request.table, records=insert_body,tokenization= request.return_tokens, upsert=request.upsert, homogeneous=request.homogeneous, byot=request.token_mode.value, request_options={'additional_headers': self.__get_headers()})
insert_response = parse_insert_response(api_response, request.continue_on_error)
@@ -128,12 +128,12 @@ def update(self, request: UpdateRequest) -> UpdateResponse:
log_info(SkyflowMessages.Info.UPDATE_REQUEST_RESOLVED.value, self.__vault_client.get_logger())
self.__initialize()
field = {key: value for key, value in request.data.items() if key != ResponseField.SKYFLOW_ID}
- record = V1FieldRecords(fields=field, tokens = request.tokens)
+ record = FieldRecords(fields=field, tokens = request.tokens)
records_api = self.__vault_client.get_records_api()
try:
log_info(SkyflowMessages.Info.UPDATE_TRIGGERED.value, self.__vault_client.get_logger())
- api_response = records_api.record_service_update_record(
+ api_response = records_api.update_record(
self.__vault_client.get_vault_id(),
request.table,
id=request.data.get(ResponseField.SKYFLOW_ID),
@@ -157,7 +157,7 @@ def delete(self, request: DeleteRequest) -> DeleteResponse:
records_api = self.__vault_client.get_records_api()
try:
log_info(SkyflowMessages.Info.DELETE_TRIGGERED.value, self.__vault_client.get_logger())
- api_response = records_api.record_service_bulk_delete_record(
+ api_response = records_api.delete_records(
self.__vault_client.get_vault_id(),
request.table,
skyflow_ids=request.ids,
@@ -179,7 +179,7 @@ def get(self, request: GetRequest) -> GetResponse:
try:
log_info(SkyflowMessages.Info.GET_TRIGGERED.value, self.__vault_client.get_logger())
- api_response = records_api.record_service_bulk_get_record(
+ api_response = records_api.get_records(
self.__vault_client.get_vault_id(),
object_name=request.table,
skyflow_ids=request.ids,
@@ -208,7 +208,7 @@ def query(self, request: QueryRequest) -> QueryResponse:
query_api = self.__vault_client.get_query_api()
try:
log_info(SkyflowMessages.Info.QUERY_TRIGGERED.value, self.__vault_client.get_logger())
- api_response = query_api.query_service_execute_query(
+ api_response = query_api.execute_query(
self.__vault_client.get_vault_id(),
query=request.query,
request_options={'additional_headers': self.__get_headers()}
@@ -226,7 +226,7 @@ def detokenize(self, request: DetokenizeRequest) -> DetokenizeResponse:
log_info(SkyflowMessages.Info.DETOKENIZE_REQUEST_RESOLVED.value, self.__vault_client.get_logger())
self.__initialize()
tokens_list = [
- V1DetokenizeRecordRequest(
+ DetokenizeRecordRequest(
token=item.get(ResponseField.TOKEN),
redaction=item.get(RequestParameter.REDACTION_TYPE) or item.get(RequestParameter.REDACTION, RedactionType.DEFAULT)
)
@@ -235,7 +235,7 @@ def detokenize(self, request: DetokenizeRequest) -> DetokenizeResponse:
tokens_api = self.__vault_client.get_tokens_api().with_raw_response
try:
log_info(SkyflowMessages.Info.DETOKENIZE_TRIGGERED.value, self.__vault_client.get_logger())
- api_response = tokens_api.record_service_detokenize(
+ api_response = tokens_api.detokenize(
self.__vault_client.get_vault_id(),
detokenization_parameters=tokens_list,
continue_on_error = request.continue_on_error,
@@ -255,13 +255,13 @@ def tokenize(self, request: TokenizeRequest) -> TokenizeResponse:
self.__initialize()
records_list = [
- V1TokenizeRecordRequest(value=item[RequestParameter.VALUE], column_group=item[RequestParameter.COLUMN_GROUP])
+ TokenizeRecordRequest(value=item[RequestParameter.VALUE], column_group=item[RequestParameter.COLUMN_GROUP])
for item in request.values
]
tokens_api = self.__vault_client.get_tokens_api()
try:
log_info(SkyflowMessages.Info.TOKENIZE_TRIGGERED.value, self.__vault_client.get_logger())
- api_response = tokens_api.record_service_tokenize(
+ api_response = tokens_api.tokenize(
self.__vault_client.get_vault_id(),
tokenization_parameters=records_list,
request_options={'additional_headers': self.__get_headers()}
@@ -278,9 +278,9 @@ def upload_file(self, request: FileUploadRequest) -> FileUploadResponse:
log_info(SkyflowMessages.Info.VALIDATING_FILE_UPLOAD_REQUEST.value, self.__vault_client.get_logger())
validate_file_upload_request(self.__vault_client.get_logger(), request)
self.__initialize()
- file_upload_api = self.__vault_client.get_records_api().with_raw_response
+ file_upload_api = self.__vault_client.get_files_api().with_raw_response
try:
- api_response = file_upload_api.upload_file_v_2(
+ api_response = file_upload_api.upload_file_v2(
self.__vault_client.get_vault_id(),
table_name=request.table,
column_name=request.column_name,
diff --git a/skyvault/skyflow/vault/detect/__init__.py b/skyvault/skyflow/vault/detect/__init__.py
index bd09fed8..15517bb2 100644
--- a/skyvault/skyflow/vault/detect/__init__.py
+++ b/skyvault/skyflow/vault/detect/__init__.py
@@ -1,14 +1,36 @@
-from ._date_transformation import DateTransformation
-from ._deidentify_text_request import DeidentifyTextRequest
-from ._deidentify_text_response import DeidentifyTextResponse
-from ._entity_info import EntityInfo
-from ._reidentify_text_request import ReidentifyTextRequest
-from ._reidentify_text_response import ReidentifyTextResponse
-from ._text_index import TextIndex
-from ._token_format import TokenFormat
-from ._transformations import Transformations
-from ._deidentify_file_request import DeidentifyFileRequest
-from ._audio_bleep import Bleep
-from ._deidentify_file_response import DeidentifyFileResponse
-from ._get_detect_run_request import GetDetectRunRequest
-from ._file_input import FileInput
\ No newline at end of file
+from common.vault.detect import (
+ DetectController,
+ Audio,
+ Bleep,
+ CheckGuardrailsRequest,
+ CheckGuardrailsResponse,
+ CustomType,
+ DeidentifyFileRequest,
+ DeidentifyFileResponse,
+ DeidentifyStringRequest,
+ DeidentifyStringResponse,
+ Detect,
+ DetectConfiguration,
+ DetectedEntity,
+ Document,
+ Entity,
+ EntityLocation,
+ FileMapping,
+ FileOutput,
+ GetRunRequest,
+ GetRunResponse,
+ Image,
+ Media,
+ Metrics,
+ ObjectEntity,
+ Pdf,
+ PollOptions,
+ ReidentifyFileRequest,
+ ReidentifyFileResponse,
+ ReidentifyStringRequest,
+ ReidentifyStringResponse,
+ ShiftDates,
+ Transformation,
+)
+
+from ._redaction_level import RedactionLevel
diff --git a/skyvault/skyflow/vault/detect/_audio_bleep.py b/skyvault/skyflow/vault/detect/_audio_bleep.py
deleted file mode 100644
index 745b7d46..00000000
--- a/skyvault/skyflow/vault/detect/_audio_bleep.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from typing import Optional
-
-class Bleep:
- def __init__(
- self,
- gain: Optional[float] = None,
- frequency: Optional[float] = None,
- start_padding: Optional[float] = None,
- stop_padding: Optional[float] = None
- ):
- self.gain = gain
- self.frequency = frequency
- self.start_padding = start_padding
- self.stop_padding = stop_padding
\ No newline at end of file
diff --git a/skyvault/skyflow/vault/detect/_date_transformation.py b/skyvault/skyflow/vault/detect/_date_transformation.py
deleted file mode 100644
index c12199c2..00000000
--- a/skyvault/skyflow/vault/detect/_date_transformation.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from typing import List
-from skyflow.utils.enums.detect_entities import DetectEntities
-
-class DateTransformation:
- def __init__(self, max_days: int, min_days: int, entities: List[DetectEntities]):
- self.max = max_days
- self.min = min_days
- self.entities = entities
diff --git a/skyvault/skyflow/vault/detect/_deidentify_file_request.py b/skyvault/skyflow/vault/detect/_deidentify_file_request.py
deleted file mode 100644
index 09d8b118..00000000
--- a/skyvault/skyflow/vault/detect/_deidentify_file_request.py
+++ /dev/null
@@ -1,43 +0,0 @@
-from typing import List, Optional, Union
-from skyflow.utils.enums import DetectEntities
-from skyflow.vault.detect import TokenFormat, Transformations
-from skyflow.vault.detect._audio_bleep import Bleep
-from skyflow.utils.enums import MaskingMethod, DetectOutputTranscriptions
-from skyflow.vault.detect._file_input import FileInput
-
-class DeidentifyFileRequest:
- def __init__(
- self,
- file = None,
- entities: Optional[List[DetectEntities]] = None,
- allow_regex_list: Optional[List[str]] = None,
- restrict_regex_list: Optional[List[str]] = None,
- token_format: Optional[TokenFormat] = None,
- transformations: Optional[Transformations] = None,
- output_processed_image: Optional[bool] = None,
- output_ocr_text: Optional[bool] = None,
- masking_method: Optional[MaskingMethod] = None,
- pixel_density: Optional[Union[int, float]] = None,
- max_resolution: Optional[Union[int, float]] = None,
- output_processed_audio: Optional[bool] = None,
- output_transcription: Optional[DetectOutputTranscriptions] = None,
- bleep: Optional[Bleep] = None,
- output_directory: Optional[str] = None,
- wait_time: Optional[Union[int, float]] = None
- ):
- self.file: FileInput = file
- self.entities: Optional[List[DetectEntities]] = entities
- self.allow_regex_list: Optional[List[str]] = allow_regex_list
- self.restrict_regex_list: Optional[List[str]] = restrict_regex_list
- self.token_format: Optional[TokenFormat] = token_format
- self.transformations: Optional[Transformations] = transformations
- self.output_processed_image: Optional[bool] = output_processed_image
- self.output_ocr_text: Optional[bool] = output_ocr_text
- self.masking_method: Optional[MaskingMethod] = masking_method
- self.pixel_density: Optional[Union[int, float]] = pixel_density
- self.max_resolution: Optional[Union[int, float]] = max_resolution
- self.output_processed_audio: Optional[bool] = output_processed_audio
- self.output_transcription: Optional[DetectOutputTranscriptions] = output_transcription
- self.bleep: Optional[Bleep] = bleep
- self.output_directory: Optional[str] = output_directory
- self.wait_time: Optional[Union[int, float]] = wait_time
\ No newline at end of file
diff --git a/skyvault/skyflow/vault/detect/_deidentify_file_response.py b/skyvault/skyflow/vault/detect/_deidentify_file_response.py
deleted file mode 100644
index e56f2113..00000000
--- a/skyvault/skyflow/vault/detect/_deidentify_file_response.py
+++ /dev/null
@@ -1,50 +0,0 @@
-import io
-from typing import Optional
-from skyflow.vault.detect._file import File
-
-class DeidentifyFileResponse:
- def __init__(
- self,
- file_base64: Optional[str] = None,
- file: Optional[io.BytesIO] = None,
- type: Optional[str] = None,
- extension: Optional[str] = None,
- word_count: Optional[int] = None,
- char_count: Optional[int] = None,
- size_in_kb: Optional[float] = None,
- duration_in_seconds: Optional[float] = None,
- page_count: Optional[int] = None,
- slide_count: Optional[int] = None,
- entities: Optional[list] = None,
- run_id: Optional[str] = None,
- status: Optional[str] = None,
- errors: Optional[list] = None,
- ):
- self.file_base64 = file_base64
- self.file = File(file) if file else None
- self.type = type
- self.extension = extension
- self.word_count = word_count
- self.char_count = char_count
- self.size_in_kb = size_in_kb
- self.duration_in_seconds = duration_in_seconds
- self.page_count = page_count
- self.slide_count = slide_count
- self.entities = entities if entities is not None else []
- self.run_id = run_id
- self.status = status
- self.errors = errors
-
- def __repr__(self):
- return (
- f"DeidentifyFileResponse("
- f"file_base64={self.file_base64!r}, file={self.file!r}, type={self.type!r}, "
- f"extension={self.extension!r}, word_count={self.word_count!r}, "
- f"char_count={self.char_count!r}, size_in_kb={self.size_in_kb!r}, "
- f"duration_in_seconds={self.duration_in_seconds!r}, page_count={self.page_count!r}, "
- f"slide_count={self.slide_count!r}, entities={self.entities!r}, "
- f"run_id={self.run_id!r}, status={self.status!r}, errors={self.errors!r})"
- )
-
- def __str__(self):
- return self.__repr__()
\ No newline at end of file
diff --git a/skyvault/skyflow/vault/detect/_deidentify_text_request.py b/skyvault/skyflow/vault/detect/_deidentify_text_request.py
deleted file mode 100644
index 8b4a440d..00000000
--- a/skyvault/skyflow/vault/detect/_deidentify_text_request.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from typing import List, Optional
-from skyflow.utils.enums.detect_entities import DetectEntities
-from ._token_format import TokenFormat
-from ._transformations import Transformations
-
-class DeidentifyTextRequest:
- def __init__(self,
- text: str,
- entities: Optional[List[DetectEntities]] = None,
- allow_regex_list: Optional[List[str]] = None,
- restrict_regex_list: Optional[List[str]] = None,
- token_format: Optional[TokenFormat] = None,
- transformations: Optional[Transformations] = None):
- self.text = text
- self.entities = entities
- self.allow_regex_list = allow_regex_list
- self.restrict_regex_list = restrict_regex_list
- self.token_format = token_format
- self.transformations = transformations
diff --git a/skyvault/skyflow/vault/detect/_deidentify_text_response.py b/skyvault/skyflow/vault/detect/_deidentify_text_response.py
deleted file mode 100644
index 227b43bc..00000000
--- a/skyvault/skyflow/vault/detect/_deidentify_text_response.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from typing import List, Optional
-from ._entity_info import EntityInfo
-
-class DeidentifyTextResponse:
- def __init__(self,
- processed_text: str,
- entities: List[EntityInfo],
- word_count: int,
- char_count: int,
- errors: Optional[list] = None):
- self.processed_text = processed_text
- self.entities = entities
- self.word_count = word_count
- self.char_count = char_count
- self.errors = errors
-
- def __repr__(self):
- return f"DeidentifyTextResponse(processed_text='{self.processed_text}', entities={self.entities}, word_count={self.word_count}, char_count={self.char_count}, errors={self.errors})"
-
- def __str__(self):
- return self.__repr__()
\ No newline at end of file
diff --git a/skyvault/skyflow/vault/detect/_entity_info.py b/skyvault/skyflow/vault/detect/_entity_info.py
deleted file mode 100644
index 1eb5f132..00000000
--- a/skyvault/skyflow/vault/detect/_entity_info.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from typing import Dict
-from ._text_index import TextIndex
-
-class EntityInfo:
- def __init__(self, token: str, value: str, text_index: TextIndex,
- processed_index: TextIndex, entity: str, scores: Dict[str, float]):
- self.token = token
- self.value = value
- self.text_index = text_index
- self.processed_index = processed_index
- self.entity = entity
- self.scores = scores
-
- def __repr__(self) -> str:
- return (f"EntityInfo(token='{self.token}', value='{self.value}', "
- f"text_index={self.text_index}, processed_index={self.processed_index}, "
- f"entity='{self.entity}', scores={self.scores})")
-
- def __str__(self) -> str:
- return self.__repr__()
\ No newline at end of file
diff --git a/skyvault/skyflow/vault/detect/_file.py b/skyvault/skyflow/vault/detect/_file.py
deleted file mode 100644
index ad188666..00000000
--- a/skyvault/skyflow/vault/detect/_file.py
+++ /dev/null
@@ -1,53 +0,0 @@
-import io
-import mimetypes
-import time
-
-class File:
- def __init__(self, file: io.BytesIO = None):
- self.file = file
-
- @property
- def name(self) -> str:
- """Get file name"""
- if self.file:
- return getattr(self.file, 'name', 'unknown')
- return None
-
- @property
- def size(self) -> int:
- """Get file size in bytes"""
- if self.file:
- pos = self.file.tell()
- self.file.seek(0, io.SEEK_END)
- size = self.file.tell()
- self.file.seek(pos)
- return size
- return None
-
- @property
- def type(self) -> str:
- """Get file mime type"""
- if self.file:
- return mimetypes.guess_type(self.name)[0] or ''
- return None
-
- @property
- def last_modified(self) -> int:
- """Get file last modified timestamp in milliseconds"""
- if self.file:
- return int(time.time() * 1000)
- return None
-
- def seek(self, offset, whence=0):
- if self.file:
- return self.file.seek(offset, whence)
-
- def read(self, size=-1):
- if self.file:
- return self.file.read(size)
-
- def __repr__(self):
- return (
- f"File(name={self.name!r}, size={self.size!r}, type={self.type!r}, "
- f"last_modified={self.last_modified!r})"
- )
diff --git a/skyvault/skyflow/vault/detect/_file_input.py b/skyvault/skyflow/vault/detect/_file_input.py
deleted file mode 100644
index 6b8bc2fb..00000000
--- a/skyvault/skyflow/vault/detect/_file_input.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from io import BufferedReader
-
-class FileInput:
- """
- Represents a file input for the vault detection process.
-
- Attributes:
- file (BufferedReader): The file object to be processed. This can be a file-like object or a binary string.
- file_path (str): The path to the file to be processed.
- """
-
- def __init__(self, file: BufferedReader= None, file_path: str = None):
- self.file = file
- self.file_path = file_path
-
- def __repr__(self) -> str:
- return f"FileInput(file={self.file!r}, file_path={self.file_path!r})"
-
- def __str__(self) -> str:
- return self.__repr__()
-
\ No newline at end of file
diff --git a/skyvault/skyflow/vault/detect/_get_detect_run_request.py b/skyvault/skyflow/vault/detect/_get_detect_run_request.py
deleted file mode 100644
index 14426458..00000000
--- a/skyvault/skyflow/vault/detect/_get_detect_run_request.py
+++ /dev/null
@@ -1,6 +0,0 @@
-class GetDetectRunRequest:
- def __init__(
- self,
- run_id: str,
- ):
- self.run_id: str = run_id
\ No newline at end of file
diff --git a/skyvault/skyflow/vault/detect/_redaction_level.py b/skyvault/skyflow/vault/detect/_redaction_level.py
new file mode 100644
index 00000000..9e461387
--- /dev/null
+++ b/skyvault/skyflow/vault/detect/_redaction_level.py
@@ -0,0 +1,14 @@
+from common.vault.detect import RedactionRule
+
+
+class RedactionLevel(RedactionRule):
+ def __init__(self, entity_name: "EntityType" = None,
+ redaction_type: "RedactionType" = None):
+ self.entity_name = entity_name
+ self.redaction_type = redaction_type
+
+ def _api_entity_name(self):
+ return self.entity_name
+
+ def _api_redaction_type(self):
+ return self.redaction_type
diff --git a/skyvault/skyflow/vault/detect/_reidentify_text_request.py b/skyvault/skyflow/vault/detect/_reidentify_text_request.py
deleted file mode 100644
index 7a7a744d..00000000
--- a/skyvault/skyflow/vault/detect/_reidentify_text_request.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from typing import List, Optional
-from skyflow.utils.enums.detect_entities import DetectEntities
-
-class ReidentifyTextRequest:
- def __init__(self, text: str,
- redacted_entities: Optional[List[DetectEntities]] = None,
- masked_entities: Optional[List[DetectEntities]] = None,
- plain_text_entities: Optional[List[DetectEntities]] = None):
- self.text = text
- self.redacted_entities = redacted_entities
- self.masked_entities = masked_entities
- self.plain_text_entities = plain_text_entities
diff --git a/skyvault/skyflow/vault/detect/_reidentify_text_response.py b/skyvault/skyflow/vault/detect/_reidentify_text_response.py
deleted file mode 100644
index 73ad3f5d..00000000
--- a/skyvault/skyflow/vault/detect/_reidentify_text_response.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from typing import Optional
-
-class ReidentifyTextResponse:
- def __init__(self, processed_text: str, errors: Optional[list] = None):
- self.processed_text = processed_text
- self.errors = errors
-
- def __repr__(self) -> str:
- return f"ReidentifyTextResponse(processed_text='{self.processed_text}', errors={self.errors})"
-
- def __str__(self) -> str:
- return self.__repr__()
\ No newline at end of file
diff --git a/skyvault/skyflow/vault/detect/_text_index.py b/skyvault/skyflow/vault/detect/_text_index.py
deleted file mode 100644
index add71c53..00000000
--- a/skyvault/skyflow/vault/detect/_text_index.py
+++ /dev/null
@@ -1,10 +0,0 @@
-class TextIndex:
- def __init__(self, start: int, end: int):
- self.start = start
- self.end = end
-
- def __repr__(self):
- return f"TextIndex(start={self.start}, end={self.end})"
-
- def __str__(self):
- return self.__repr__()
diff --git a/skyvault/skyflow/vault/detect/_token_format.py b/skyvault/skyflow/vault/detect/_token_format.py
deleted file mode 100644
index a8d2b2db..00000000
--- a/skyvault/skyflow/vault/detect/_token_format.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from typing import List
-from skyflow.utils.enums.detect_entities import DetectEntities
-from skyflow.utils.enums.token_type import TokenType
-
-class TokenFormat:
- def __init__(self, default: TokenType = TokenType.ENTITY_UNIQUE_COUNTER,
- vault_token: List[DetectEntities] = None,
- entity_unique_counter: List[DetectEntities] = None,
- entity_only: List[DetectEntities] = None):
- self.default = default
- self.vault_token = vault_token
- self.entity_unique_counter = entity_unique_counter
- self.entity_only = entity_only
diff --git a/skyvault/skyflow/vault/detect/_transformations.py b/skyvault/skyflow/vault/detect/_transformations.py
deleted file mode 100644
index af6bff56..00000000
--- a/skyvault/skyflow/vault/detect/_transformations.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from skyflow.vault.detect._date_transformation import DateTransformation
-
-class Transformations:
- def __init__(self, shift_dates: DateTransformation):
- self.shift_dates = shift_dates
diff --git a/skyvault/tests/client/test_skyflow.py b/skyvault/tests/client/test_skyflow.py
index df95c32f..d04554b4 100644
--- a/skyvault/tests/client/test_skyflow.py
+++ b/skyvault/tests/client/test_skyflow.py
@@ -365,15 +365,15 @@ def test_skyflow_vault_and_connection_method(self, mock_get_vault_config):
def test_detect_returns_detect_controller(self):
skyflow_client = self.builder.add_vault_config(VALID_VAULT_CONFIG).build()
- from skyflow.vault.controller import Detect
+ from skyflow.vault.detect import DetectController
result = skyflow_client.detect()
- self.assertIsInstance(result, Detect)
+ self.assertIsInstance(result, DetectController)
def test_detect_with_explicit_vault_id(self):
skyflow_client = self.builder.add_vault_config(VALID_VAULT_CONFIG).build()
- from skyflow.vault.controller import Detect
+ from skyflow.vault.detect import DetectController
result = skyflow_client.detect(VALID_VAULT_CONFIG["vault_id"])
- self.assertIsInstance(result, Detect)
+ self.assertIsInstance(result, DetectController)
def test_detect_with_invalid_vault_id_raises_error(self):
skyflow_client = self.builder.add_vault_config(VALID_VAULT_CONFIG).build()
@@ -413,17 +413,23 @@ class TestVaultClient(unittest.TestCase):
def _make_client(self):
client = VaultClient({"vault_id": "test_vault"})
client._api_client = Mock()
+ client._detect_api_client = Mock()
return client
- def test_get_detect_text_api_returns_strings(self):
+ def test_get_strings_v2_api_returns_strings_v2(self):
client = self._make_client()
- result = client.get_detect_text_api()
- self.assertEqual(result, client._api_client.strings)
+ result = client.get_strings_v2_api()
+ self.assertEqual(result, client._detect_api_client.strings_v2)
- def test_get_detect_file_api_returns_files(self):
+ def test_get_files_v2_api_returns_files_v2(self):
client = self._make_client()
- result = client.get_detect_file_api()
- self.assertEqual(result, client._api_client.files)
+ result = client.get_files_v2_api()
+ self.assertEqual(result, client._detect_api_client.files_v2)
+
+ def test_get_guardrails_v2_api_returns_guardrails_v2(self):
+ client = self._make_client()
+ result = client.get_guardrails_v2_api()
+ self.assertEqual(result, client._detect_api_client.guardrails_v2)
@patch("common.vault.base_vault_client.generate_bearer_token_from_creds")
@patch("common.vault.base_vault_client.is_expired", return_value=True)
diff --git a/skyvault/tests/service_account/test__utils.py b/skyvault/tests/service_account/test__utils.py
index 053a1c96..646a3ddd 100644
--- a/skyvault/tests/service_account/test__utils.py
+++ b/skyvault/tests/service_account/test__utils.py
@@ -90,7 +90,7 @@ def test_generate_bearer_token_invalid_json(self, mock_json_load):
generate_bearer_token(creds_path)
self.assertEqual(context.exception.message, SkyflowMessages.Error.FILE_INVALID_JSON.value.format(creds_path))
- @patch("skyflow.service_account._utils.get_service_account_token")
+ @patch("common.service_account._utils.get_service_account_token")
def test_generate_bearer_token_valid_file_path(self, mock_generate_bearer_token):
creds_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "credentials.json")
generate_bearer_token(creds_path)
@@ -98,7 +98,7 @@ def test_generate_bearer_token_valid_file_path(self, mock_generate_bearer_token)
# ── generate_bearer_token_from_creds ──────────────────────────────────────
- @patch("skyflow.service_account._utils.get_service_account_token")
+ @patch("common.service_account._utils.get_service_account_token")
def test_generate_bearer_token_from_creds_with_valid_json_string(self, mock_generate_bearer_token):
generate_bearer_token_from_creds(VALID_CREDENTIALS_STRING)
mock_generate_bearer_token.assert_called_once()
diff --git a/skyvault/tests/utils/test__utils.py b/skyvault/tests/utils/test__utils.py
index c29f57f3..bc53eea5 100644
--- a/skyvault/tests/utils/test__utils.py
+++ b/skyvault/tests/utils/test__utils.py
@@ -29,9 +29,6 @@
handle_exception,
validate_api_key,
encode_column_values,
- parse_deidentify_text_response,
- parse_reidentify_text_response,
- convert_detected_entity_to_entity_info,
)
from skyflow.utils._utils import parse_path_params, to_lowercase_keys, get_metrics, handle_json_error, r_urlencode
from skyflow.utils.enums import EnvUrls, Env, ContentType
@@ -589,104 +586,6 @@ def test_encode_column_values(self):
result = encode_column_values(get_request)
self.assertEqual(result, expected_encoded_values)
- def test_parse_deidentify_text_response(self):
- """Test parsing deidentify text response with multiple entities."""
- mock_entity = Mock()
- mock_entity.token = "token123"
- mock_entity.value = "sensitive_value"
- mock_entity.entity_type = "EMAIL"
- mock_entity.entity_scores = {"EMAIL": 0.95}
- mock_entity.location = Mock(start_index=10, end_index=20, start_index_processed=15, end_index_processed=25)
-
- mock_api_response = Mock()
- mock_api_response.processed_text = "Sample processed text"
- mock_api_response.entities = [mock_entity]
- mock_api_response.word_count = 3
- mock_api_response.character_count = 20
-
- result = parse_deidentify_text_response(mock_api_response)
-
- self.assertEqual(result.processed_text, "Sample processed text")
- self.assertEqual(result.word_count, 3)
- self.assertEqual(result.char_count, 20)
- self.assertEqual(len(result.entities), 1)
-
- entity = result.entities[0]
- self.assertEqual(entity.token, "token123")
- self.assertEqual(entity.value, "sensitive_value")
- self.assertEqual(entity.entity, "EMAIL")
- self.assertEqual(entity.scores, {"EMAIL": 0.95})
- self.assertEqual(entity.text_index.start, 10)
- self.assertEqual(entity.text_index.end, 20)
- self.assertEqual(entity.processed_index.start, 15)
- self.assertEqual(entity.processed_index.end, 25)
-
- def test_parse_deidentify_text_response_no_entities(self):
- """Test parsing deidentify text response with no entities."""
- mock_api_response = Mock()
- mock_api_response.processed_text = "Sample processed text"
- mock_api_response.entities = []
- mock_api_response.word_count = 3
- mock_api_response.character_count = 20
-
- result = parse_deidentify_text_response(mock_api_response)
-
- self.assertEqual(result.processed_text, "Sample processed text")
- self.assertEqual(result.word_count, 3)
- self.assertEqual(result.char_count, 20)
- self.assertEqual(len(result.entities), 0)
-
- def test_parse_reidentify_text_response(self):
- """Test parsing reidentify text response."""
- mock_api_response = Mock()
- mock_api_response.text = "Reidentified text with actual values"
-
- result = parse_reidentify_text_response(mock_api_response)
-
- self.assertEqual(result.processed_text, "Reidentified text with actual values")
-
- def test__convert_detected_entity_to_entity_info(self):
- """Test converting detected entity to EntityInfo object."""
- mock_detected_entity = Mock()
- mock_detected_entity.token = "token123"
- mock_detected_entity.value = "sensitive_value"
- mock_detected_entity.entity_type = "EMAIL"
- mock_detected_entity.entity_scores = {"EMAIL": 0.95}
- mock_detected_entity.location = Mock(
- start_index=10, end_index=20, start_index_processed=15, end_index_processed=25
- )
-
- result = convert_detected_entity_to_entity_info(mock_detected_entity)
-
- self.assertEqual(result.token, "token123")
- self.assertEqual(result.value, "sensitive_value")
- self.assertEqual(result.entity, "EMAIL")
- self.assertEqual(result.scores, {"EMAIL": 0.95})
- self.assertEqual(result.text_index.start, 10)
- self.assertEqual(result.text_index.end, 20)
- self.assertEqual(result.processed_index.start, 15)
- self.assertEqual(result.processed_index.end, 25)
-
- def test__convert_detected_entity_to_entity_info_with_minimal_data(self):
- """Test converting detected entity with minimal required data."""
- mock_detected_entity = Mock()
- mock_detected_entity.token = "token123"
- mock_detected_entity.value = None
- mock_detected_entity.entity_type = "UNKNOWN"
- mock_detected_entity.entity_scores = {}
- mock_detected_entity.location = Mock(start_index=0, end_index=0, start_index_processed=0, end_index_processed=0)
-
- result = convert_detected_entity_to_entity_info(mock_detected_entity)
-
- self.assertEqual(result.token, "token123")
- self.assertIsNone(result.value)
- self.assertEqual(result.entity, "UNKNOWN")
- self.assertEqual(result.scores, {})
- self.assertEqual(result.text_index.start, 0)
- self.assertEqual(result.text_index.end, 0)
- self.assertEqual(result.processed_index.start, 0)
- self.assertEqual(result.processed_index.end, 0)
-
@patch("skyflow.utils._utils.log_and_reject_error")
def test_handle_exception_connect_error(self, mock_log_and_reject_error):
"""Test handling httpx.ConnectError."""
@@ -1492,11 +1391,11 @@ def test_generate_bearer_token_options_override_token_uri(self):
json.dump(creds, tmp)
tmp.flush()
# Patch AuthClient and jwt.encode to avoid real HTTP and signing
- with patch("skyflow.service_account._utils.get_signed_jwt") as mock_get_signed_jwt:
+ with patch("common.service_account._utils.get_signed_jwt") as mock_get_signed_jwt:
mock_get_signed_jwt.return_value = "signed"
- with patch("skyflow.service_account._utils.AuthClient") as mock_auth_client:
+ with patch("common.service_account._utils.AuthClient") as mock_auth_client:
mock_auth_api = mock_auth_client.return_value.get_auth_api.return_value
- mock_auth_api.authentication_service_get_auth_token.return_value = type(
+ mock_auth_api.get_bearer_token.return_value = type(
"obj", (), {"access_token": "token", "token_type": "bearer"}
)
generate_bearer_token(tmp.name, options)
@@ -1526,11 +1425,11 @@ def test_generate_bearer_token_from_creds_options_override_token_uri(self):
}
options = {"token_uri": "https://another-valid-url.com"}
creds_str = json.dumps(creds)
- with patch("skyflow.service_account._utils.get_signed_jwt") as mock_get_signed_jwt:
+ with patch("common.service_account._utils.get_signed_jwt") as mock_get_signed_jwt:
mock_get_signed_jwt.return_value = "signed"
- with patch("skyflow.service_account._utils.AuthClient") as mock_auth_client:
+ with patch("common.service_account._utils.AuthClient") as mock_auth_client:
mock_auth_api = mock_auth_client.return_value.get_auth_api.return_value
- mock_auth_api.authentication_service_get_auth_token.return_value = type(
+ mock_auth_api.get_bearer_token.return_value = type(
"obj", (), {"access_token": "token", "token_type": "bearer"}
)
generate_bearer_token_from_creds(creds_str, options)
diff --git a/skyvault/tests/utils/validations/test__validations.py b/skyvault/tests/utils/validations/test__validations.py
index f55d1a4f..82a66030 100644
--- a/skyvault/tests/utils/validations/test__validations.py
+++ b/skyvault/tests/utils/validations/test__validations.py
@@ -9,18 +9,15 @@
validate_required_field, validate_api_key, validate_credentials,
validate_log_level, validate_keys, validate_vault_config,
validate_update_vault_config, validate_connection_config,
- validate_update_connection_config, validate_file_from_request,
+ validate_update_connection_config,
validate_insert_request, validate_delete_request, validate_query_request,
- validate_get_detect_run_request, validate_get_request, validate_update_request,
+ validate_get_request, validate_update_request,
validate_detokenize_request, validate_tokenize_request, validate_invoke_connection_params,
- validate_deidentify_text_request, validate_reidentify_text_request, validate_deidentify_file_request,
validate_file_upload_request, validate_token_options
)
from skyflow.utils import SkyflowMessages
-from skyflow.utils.enums import DetectEntities, RedactionType
+from skyflow.utils.enums import RedactionType
from skyflow.vault.data import GetRequest, UpdateRequest
-from skyflow.vault.detect import DeidentifyTextRequest, Transformations, DateTransformation, ReidentifyTextRequest, \
- FileInput, DeidentifyFileRequest, Bleep
from skyflow.vault.data._file_upload_request import FileUploadRequest
from skyflow.vault.tokens import DetokenizeRequest
from skyflow.vault.connection._invoke_connection_request import InvokeConnectionRequest
@@ -461,47 +458,6 @@ def test_validate_update_connection_config_invalid_credentials_includes_connecti
self.assertEqual(context.exception.message,
SkyflowMessages.Error.INVALID_CREDENTIALS_IN_CONFIG.value.format("connection", "conn123"))
- def test_validate_file_from_request_valid_file(self):
- file_obj = MagicMock()
- file_obj.name = "test.txt"
- file_input = MagicMock()
- file_input.file = file_obj
- file_input.file_path = None
- validate_file_from_request(file_input)
-
- def test_validate_file_from_request_valid_file_path(self):
- file_input = MagicMock()
- file_input.file = None
- file_input.file_path = self.temp_file_path
- validate_file_from_request(file_input)
-
- def test_validate_file_from_request_missing_both(self):
- file_input = MagicMock()
- file_input.file = None
- file_input.file_path = None
- with self.assertRaises(SkyflowError) as context:
- validate_file_from_request(file_input)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_DEIDENTIFY_FILE_INPUT.value)
-
- def test_validate_file_from_request_both_provided(self):
- file_obj = MagicMock()
- file_obj.name = "test.txt"
- file_input = MagicMock()
- file_input.file = file_obj
- file_input.file_path = "/path/to/file"
- with self.assertRaises(SkyflowError) as context:
- validate_file_from_request(file_input)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_DEIDENTIFY_FILE_INPUT.value)
-
-
- def test_validate_file_from_request_invalid_file_path(self):
- file_input = MagicMock()
- file_input.file = None
- file_input.file_path = "/nonexistent/path/to/file"
- with self.assertRaises(SkyflowError) as context:
- validate_file_from_request(file_input)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_DEIDENTIFY_FILE_PATH.value)
-
def test_validate_insert_request_valid(self):
request = MagicMock()
request.table = "test_table"
@@ -606,25 +562,6 @@ def test_validate_query_request_non_select_query(self):
validate_query_request(self.logger, request)
self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_QUERY_COMMAND.value.format(request.query))
- def test_validate_get_detect_run_request_valid(self):
- request = MagicMock()
- request.run_id = "test_run_123"
- validate_get_detect_run_request(self.logger, request)
-
- def test_validate_get_detect_run_request_empty_run_id(self):
- request = MagicMock()
- request.run_id = ""
- with self.assertRaises(SkyflowError) as context:
- validate_get_detect_run_request(self.logger, request)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_RUN_ID.value)
-
- def test_validate_get_detect_run_request_invalid_run_id_type(self):
- request = MagicMock()
- request.run_id = 123 # Invalid type
- with self.assertRaises(SkyflowError) as context:
- validate_get_detect_run_request(self.logger, request)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_RUN_ID.value)
-
def test_validate_get_request_valid(self):
from skyflow.utils.enums import RedactionType
request = MagicMock()
@@ -887,348 +824,6 @@ class NonSerializable:
validate_invoke_connection_params(self.logger, request.query_params, request.path_params)
self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_QUERY_PARAMS.value)
- def test_validate_deidentify_text_request_valid(self):
- request = DeidentifyTextRequest(
- text="test",
- entities=None,
- allow_regex_list=None,
- restrict_regex_list = None,
- token_format = None,
- transformations = None,
- )
- validate_deidentify_text_request(self.logger, request)
-
- def test_validate_reidentify_text_request_valid(self):
- request = ReidentifyTextRequest(
- text="test",
- masked_entities=[DetectEntities.CREDIT_CARD],
- redacted_entities=[DetectEntities.SSN],
- plain_text_entities=None,
- )
- validate_reidentify_text_request(self.logger, request)
-
- def test_validate_reidentify_text_request_empty_text(self):
- request = ReidentifyTextRequest(
- text="",
- masked_entities=[DetectEntities.CREDIT_CARD],
- redacted_entities=[DetectEntities.SSN],
- )
- with self.assertRaises(SkyflowError) as context:
- validate_reidentify_text_request(self.logger, request)
- self.assertEqual(context.exception.message,
- SkyflowMessages.Error.INVALID_TEXT_IN_REIDENTIFY.value)
-
- def test_validate_reidentify_text_request_invalid_redacted_entities(self):
- request = ReidentifyTextRequest(
- text="test",
- redacted_entities="invalid",
- )
- with self.assertRaises(SkyflowError) as context:
- validate_reidentify_text_request(self.logger, request)
- self.assertEqual(context.exception.message,
- SkyflowMessages.Error.INVALID_REDACTED_ENTITIES_IN_REIDENTIFY.value)
-
- def test_validate_reidentify_text_request_invalid_plain_text_entities(self):
- request = ReidentifyTextRequest(
- text="test",
- plain_text_entities="invalid",
- )
- with self.assertRaises(SkyflowError) as context:
- validate_reidentify_text_request(self.logger, request)
- self.assertEqual(context.exception.message,
- SkyflowMessages.Error.INVALID_PLAIN_TEXT_ENTITIES_IN_REIDENTIFY.value)
-
-
- def test_validate_deidentify_text_request_empty_text(self):
- request = DeidentifyTextRequest(
- text="",
- entities=None,
- allow_regex_list=None,
- restrict_regex_list=None,
- token_format=None,
- transformations=None,
- )
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_text_request(self.logger, request)
- self.assertEqual(context.exception.message,
- SkyflowMessages.Error.INVALID_TEXT_IN_DEIDENTIFY.value)
-
- def test_validate_deidentify_text_request_invalid_text_type(self):
- request = DeidentifyTextRequest(
- text=["test"],
- entities=None,
- allow_regex_list=None,
- restrict_regex_list=None,
- token_format=None,
- transformations=None,
- )
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_text_request(self.logger, request)
- self.assertEqual(context.exception.message,
- SkyflowMessages.Error.INVALID_TEXT_IN_DEIDENTIFY.value)
-
- def test_validate_deidentify_text_request_invalid_entities_type(self):
- request = DeidentifyTextRequest(
- text="test",
- entities="invalid",
- allow_regex_list=None,
- restrict_regex_list=None,
- token_format=None,
- transformations=None,
- )
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_text_request(self.logger, request)
- self.assertEqual(context.exception.message,
- SkyflowMessages.Error.INVALID_ENTITIES_IN_DEIDENTIFY.value)
-
- def test_validate_deidentify_text_request_invalid_allow_regex(self):
- request = DeidentifyTextRequest(
- text="test",
- allow_regex_list="invalid",
- restrict_regex_list=None,
- token_format=None,
- transformations=None,
- )
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_text_request(self.logger, request)
- self.assertEqual(context.exception.message,
- SkyflowMessages.Error.INVALID_ALLOW_REGEX_LIST.value)
-
- def test_validate_deidentify_text_request_invalid_restrict_regex(self):
- request = DeidentifyTextRequest(
- text="test",
- restrict_regex_list="invalid",
- )
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_text_request(self.logger, request)
- self.assertEqual(context.exception.message,
- SkyflowMessages.Error.INVALID_RESTRICT_REGEX_LIST.value)
-
- def test_validate_deidentify_text_request_invalid_token_format(self):
- request = DeidentifyTextRequest(
- text="test",
- token_format="invalid",
- transformations=None,
- )
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_text_request(self.logger, request)
- self.assertEqual(context.exception.message,
- SkyflowMessages.Error.INVALID_TOKEN_FORMAT.value)
-
-
- def test_validate_reidentify_text_request_valid(self):
- request = MagicMock()
- request.text = "test text"
- request.redacted_entities = None
- request.masked_entities = None
- request.plain_text_entities = None
- validate_reidentify_text_request(self.logger, request)
-
- def test_validate_reidentify_text_request_empty_text(self):
- request = MagicMock()
- request.text = "" # Empty text
- with self.assertRaises(SkyflowError) as context:
- validate_reidentify_text_request(self.logger, request)
- self.assertEqual(context.exception.message,
- SkyflowMessages.Error.INVALID_TEXT_IN_REIDENTIFY.value)
-
- def test_validate_reidentify_text_request_invalid_text_type(self):
- request = MagicMock()
- request.text = 123 # Invalid type
- with self.assertRaises(SkyflowError) as context:
- validate_reidentify_text_request(self.logger, request)
- self.assertEqual(context.exception.message,
- SkyflowMessages.Error.INVALID_TEXT_IN_REIDENTIFY.value)
-
- def test_validate_reidentify_text_request_invalid_redacted_entities(self):
- request = MagicMock()
- request.text = "test text"
- request.redacted_entities = "invalid"
- with self.assertRaises(SkyflowError) as context:
- validate_reidentify_text_request(self.logger, request)
- self.assertEqual(context.exception.message,
- SkyflowMessages.Error.INVALID_REDACTED_ENTITIES_IN_REIDENTIFY.value)
-
- def test_validate_reidentify_text_request_invalid_plain_text_entities(self):
- request = ReidentifyTextRequest(
- text="test text",
- plain_text_entities="invalid"
- )
- with self.assertRaises(SkyflowError) as context:
- validate_reidentify_text_request(self.logger, request)
- self.assertEqual(context.exception.message,
- SkyflowMessages.Error.INVALID_PLAIN_TEXT_ENTITIES_IN_REIDENTIFY.value)
-
- def test_validate_deidentify_file_request_valid(self):
- file_input = FileInput(file_path=self.temp_file_path)
- request = DeidentifyFileRequest(
- file=file_input,
- entities=None,
- allow_regex_list=None,
- restrict_regex_list=None,
- token_format=None,
- transformations=None,
- output_processed_image=None,
- output_ocr_text=None,
- masking_method=None,
- pixel_density=None,
- max_resolution=None,
- output_processed_audio=None,
- output_transcription=None,
- bleep=None,
- output_directory=None,
- wait_time=None
- )
- validate_deidentify_file_request(self.logger, request)
-
- def test_validate_deidentify_file_request_missing_file(self):
- request = DeidentifyFileRequest(file=None)
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_file_request(self.logger, request)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_FILE_INPUT.value)
-
- def test_validate_deidentify_file_request_invalid_entities(self):
- file_input = FileInput(file_path=self.temp_file_path)
- request = DeidentifyFileRequest(
- file=file_input,
- entities="invalid"
- )
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_file_request(self.logger, request)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_DETECT_ENTITIES_TYPE.value)
-
- def test_validate_deidentify_file_request_invalid_allow_regex(self):
- file_input = FileInput(file_path=self.temp_file_path)
- request = DeidentifyFileRequest(
- file=file_input,
- allow_regex_list="invalid",
- entities=[DetectEntities.ACCOUNT_NUMBER]
- )
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_file_request(self.logger, request)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_ALLOW_REGEX_LIST.value)
-
- def test_validate_deidentify_file_request_invalid_restrict_regex(self):
- file_input = FileInput(file_path=self.temp_file_path)
- request = DeidentifyFileRequest(
- file=file_input,
- restrict_regex_list="invalid",
- entities=[DetectEntities.SSN]
- )
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_file_request(self.logger, request)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_RESTRICT_REGEX_LIST.value)
-
- def test_validate_deidentify_file_request_invalid_token_format(self):
- file_input = FileInput(file_path=self.temp_file_path)
- request = DeidentifyFileRequest(
- file=file_input,
- token_format="invalid",
- entities=[DetectEntities.SSN]
- )
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_file_request(self.logger, request)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_TOKEN_FORMAT.value)
-
- def test_validate_deidentify_file_request_invalid_transformations(self):
- file_input = FileInput(file_path=self.temp_file_path)
- request = DeidentifyFileRequest(
- file=file_input,
- transformations="invalid",
- entities=[DetectEntities.SSN]
- )
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_file_request(self.logger, request)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_TRANSFORMATIONS.value)
-
- def test_validate_deidentify_file_request_invalid_output_processed_image(self):
- file_input = FileInput(file_path=self.temp_file_path)
- request = DeidentifyFileRequest(
- file=file_input,
- output_processed_image="true",
- entities=[DetectEntities.SSN]
- )
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_file_request(self.logger, request)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_OUTPUT_PROCESSED_IMAGE.value)
-
- def test_validate_deidentify_file_request_invalid_output_ocr_text(self):
- file_input = FileInput(file_path=self.temp_file_path)
- request = DeidentifyFileRequest(
- file=file_input,
- output_ocr_text="true",
- entities=[DetectEntities.SSN]
- )
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_file_request(self.logger, request)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_OUTPUT_OCR_TEXT.value)
-
- def test_validate_deidentify_file_request_invalid_masking_method(self):
- file_input = FileInput(file_path=self.temp_file_path)
- request = DeidentifyFileRequest(
- file=file_input,
- masking_method="invalid",
- entities=[DetectEntities.SSN]
- )
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_file_request(self.logger, request)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_MASKING_METHOD.value)
-
- def test_validate_deidentify_file_request_invalid_pixel_density(self):
- file_input = FileInput(file_path=self.temp_file_path)
- request = DeidentifyFileRequest(
- file=file_input,
- pixel_density="invalid",
- entities=[DetectEntities.SSN]
- )
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_file_request(self.logger, request)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_PIXEL_DENSITY.value)
-
- def test_validate_deidentify_file_request_invalid_max_resolution(self):
- file_input = FileInput(file_path=self.temp_file_path)
- request = DeidentifyFileRequest(
- file=file_input,
- max_resolution="invalid",
- entities=[DetectEntities.SSN]
- )
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_file_request(self.logger, request)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_MAXIMUM_RESOLUTION.value)
-
- def test_validate_deidentify_file_request_invalid_output_processed_audio(self):
- file_input = FileInput(file_path=self.temp_file_path)
- request = DeidentifyFileRequest(
- file=file_input,
- output_processed_audio="true",
- entities=[DetectEntities.SSN]
- )
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_file_request(self.logger, request)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_OUTPUT_PROCESSED_AUDIO.value)
-
- def test_validate_deidentify_file_request_invalid_output_transcription(self):
- file_input = FileInput(file_path=self.temp_file_path)
- request = DeidentifyFileRequest(
- file=file_input,
- output_transcription="invalid",
- entities=[DetectEntities.SSN]
- )
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_file_request(self.logger, request)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_OUTPUT_TRANSCRIPTION.value)
-
- def test_validate_deidentify_file_request_invalid_wait_time(self):
- file_input = FileInput(file_path=self.temp_file_path)
- request = DeidentifyFileRequest(
- file=file_input,
- wait_time="invalid",
- entities=[DetectEntities.SSN]
- )
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_file_request(self.logger, request)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_WAIT_TIME.value)
-
def test_validate_detokenize_request_valid(self):
request = DetokenizeRequest(
data=[{"token": "token123", "redaction": RedactionType.PLAIN_TEXT}],
@@ -1292,67 +887,6 @@ def test_validate_detokenize_request_redaction_type_only_no_warn(self):
mock_warn.assert_not_called()
- def test_validate_deidentify_file_request_wait_time_negative(self):
- file_input = FileInput(file_path=self.temp_file_path)
- request = DeidentifyFileRequest(
- file=file_input,
- wait_time=-1,
- entities=[DetectEntities.SSN]
- )
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_file_request(self.logger, request)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.WAIT_TIME_GREATER_THEN_64.value)
-
- def test_validate_deidentify_file_request_wait_time_greater_than_64(self):
- file_input = FileInput(file_path=self.temp_file_path)
- request = DeidentifyFileRequest(
- file=file_input,
- wait_time=65,
- entities=[DetectEntities.SSN]
- )
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_file_request(self.logger, request)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.WAIT_TIME_GREATER_THEN_64.value)
-
- def test_validate_deidentify_file_request_wait_time_valid_boundary_lower(self):
- file_input = FileInput(file_path=self.temp_file_path)
- request = DeidentifyFileRequest(
- file=file_input,
- wait_time=0,
- entities=[DetectEntities.SSN]
- )
- validate_deidentify_file_request(self.logger, request)
-
- def test_validate_deidentify_file_request_wait_time_valid_boundary_upper(self):
- file_input = FileInput(file_path=self.temp_file_path)
- request = DeidentifyFileRequest(
- file=file_input,
- wait_time=64,
- entities=[DetectEntities.SSN]
- )
- # Should not raise an error
- validate_deidentify_file_request(self.logger, request)
-
- def test_validate_deidentify_file_request_wait_time_valid_float(self):
- file_input = FileInput(file_path=self.temp_file_path)
- request = DeidentifyFileRequest(
- file=file_input,
- wait_time=32.5,
- entities=[DetectEntities.SSN]
- )
- # Should not raise an error
- validate_deidentify_file_request(self.logger, request)
-
- def test_validate_deidentify_file_request_wait_time_float_out_of_range(self):
- file_input = FileInput(file_path=self.temp_file_path)
- request = DeidentifyFileRequest(
- file=file_input,
- wait_time=64.1,
- entities=[DetectEntities.SSN]
- )
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_file_request(self.logger, request)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.WAIT_TIME_GREATER_THEN_64.value)
def test_validate_credentials_with_valid_token_uri(self):
credentials = {
"api_key": DUMMY_VALID_API_KEY,
@@ -1421,117 +955,6 @@ def test_validate_update_vault_config_with_invalid_token_uri_url(self):
# --- validate_file_from_request ---
- def test_validate_file_from_request_none_input(self):
- with self.assertRaises(SkyflowError) as context:
- validate_file_from_request(None)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_FILE_INPUT.value)
-
- def test_validate_file_from_request_file_without_name_attr(self):
- file_obj = MagicMock(spec=[]) # no attributes at all
- file_input = MagicMock()
- file_input.file = file_obj
- file_input.file_path = None
- with self.assertRaises(SkyflowError) as context:
- validate_file_from_request(file_input)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_FILE_TYPE.value)
-
- def test_validate_file_from_request_file_with_empty_name(self):
- file_obj = MagicMock()
- file_obj.name = " " # whitespace-only name
- file_input = MagicMock()
- file_input.file = file_obj
- file_input.file_path = None
- with self.assertRaises(SkyflowError) as context:
- validate_file_from_request(file_input)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_FILE_TYPE.value)
-
- def test_validate_file_from_request_extension_only_name(self):
- file_obj = MagicMock()
- # A trailing-slash path gives os.path.basename() == "", so splitext returns ("", "")
- file_obj.name = "/some/directory/"
- file_input = MagicMock()
- file_input.file = file_obj
- file_input.file_path = None
- with self.assertRaises(SkyflowError) as context:
- validate_file_from_request(file_input)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_FILE_NAME.value)
-
- def test_validate_file_from_request_empty_string_file_path(self):
- file_input = MagicMock()
- file_input.file = None
- file_input.file_path = "" # empty string — has_file_path=True, so goes to elif branch
- with self.assertRaises(SkyflowError) as context:
- validate_file_from_request(file_input)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_DEIDENTIFY_FILE_PATH.value)
-
- # --- validate_deidentify_file_request bleep sub-fields ---
-
- def test_validate_deidentify_file_request_invalid_bleep_type(self):
- file_input = FileInput(file_path=self.temp_file_path)
- request = DeidentifyFileRequest(file=file_input, bleep="not_a_bleep")
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_file_request(self.logger, request)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_BLEEP_TYPE.value)
-
- def test_validate_deidentify_file_request_invalid_bleep_gain(self):
- file_input = FileInput(file_path=self.temp_file_path)
- bleep = Bleep(gain="loud")
- request = DeidentifyFileRequest(file=file_input, bleep=bleep)
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_file_request(self.logger, request)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_BLEEP_GAIN.value)
-
- def test_validate_deidentify_file_request_invalid_bleep_frequency(self):
- file_input = FileInput(file_path=self.temp_file_path)
- bleep = Bleep(frequency="high")
- request = DeidentifyFileRequest(file=file_input, bleep=bleep)
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_file_request(self.logger, request)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_BLEEP_FREQUENCY.value)
-
- def test_validate_deidentify_file_request_invalid_bleep_start_padding(self):
- file_input = FileInput(file_path=self.temp_file_path)
- bleep = Bleep(start_padding="early")
- request = DeidentifyFileRequest(file=file_input, bleep=bleep)
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_file_request(self.logger, request)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_BLEEP_START_PADDING.value)
-
- def test_validate_deidentify_file_request_invalid_bleep_stop_padding(self):
- file_input = FileInput(file_path=self.temp_file_path)
- bleep = Bleep(stop_padding="late")
- request = DeidentifyFileRequest(file=file_input, bleep=bleep)
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_file_request(self.logger, request)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_BLEEP_STOP_PADDING.value)
-
- # --- validate_deidentify_file_request output_directory ---
-
- def test_validate_deidentify_file_request_invalid_output_directory_type(self):
- file_input = FileInput(file_path=self.temp_file_path)
- request = DeidentifyFileRequest(file=file_input, output_directory=123)
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_file_request(self.logger, request)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_OUTPUT_DIRECTORY_VALUE.value)
-
- def test_validate_deidentify_file_request_output_directory_not_found(self):
- file_input = FileInput(file_path=self.temp_file_path)
- nonexistent = "/tmp/skyflow_nonexistent_dir_12345"
- request = DeidentifyFileRequest(file=file_input, output_directory=nonexistent)
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_file_request(self.logger, request)
- self.assertEqual(
- context.exception.message,
- SkyflowMessages.Error.OUTPUT_DIRECTORY_NOT_FOUND.value.format(nonexistent)
- )
-
- def test_validate_deidentify_file_request_valid_output_directory(self):
- file_input = FileInput(file_path=self.temp_file_path)
- request = DeidentifyFileRequest(file=file_input, output_directory=self.temp_dir_path)
- validate_deidentify_file_request(self.logger, request)
-
- # --- validate_file_upload_request ---
-
def test_validate_file_upload_request_none(self):
with self.assertRaises(SkyflowError) as context:
validate_file_upload_request(self.logger, None)
@@ -1696,24 +1119,3 @@ def test_validate_file_upload_request_non_string_fields(self):
self.assertEqual(context.exception.message, expected_message)
# --- validate_deidentify_text_request transformations ---
-
- def test_validate_deidentify_text_request_invalid_transformations(self):
- request = DeidentifyTextRequest(
- text="test text",
- transformations="invalid_type"
- )
- with self.assertRaises(SkyflowError) as context:
- validate_deidentify_text_request(self.logger, request)
- self.assertEqual(context.exception.message, SkyflowMessages.Error.INVALID_TRANSFORMATIONS.value)
-
- # --- validate_reidentify_text_request masked_entities ---
-
- def test_validate_reidentify_text_request_invalid_masked_entities(self):
- request = ReidentifyTextRequest(
- text="test text",
- masked_entities="invalid_type"
- )
- with self.assertRaises(SkyflowError) as context:
- validate_reidentify_text_request(self.logger, request)
- self.assertEqual(context.exception.message,
- SkyflowMessages.Error.INVALID_MASKED_ENTITIES_IN_REIDENTIFY.value)
\ No newline at end of file
diff --git a/skyvault/tests/vault/client/test__client.py b/skyvault/tests/vault/client/test__client.py
index a0894567..c20eb5d4 100644
--- a/skyvault/tests/vault/client/test__client.py
+++ b/skyvault/tests/vault/client/test__client.py
@@ -71,7 +71,7 @@ def test_resolve_vault_url_uses_v2_domain(self):
# the one hook v2 actually overrides)
# ------------------------------------------------------------------ #
- @patch("skyflow.vault.client.client.Skyflow")
+ @patch("skyflow.vault.client.client.SkyflowAuth")
def test_initialize_api_client_passes_callable_token(self, mock_skyflow):
"""initialize_api_client must pass a callable (lambda) as token, not a string."""
self.vault_client.initialize_api_client("https://test-vault-url.com", "initial_token")
@@ -80,7 +80,7 @@ def test_initialize_api_client_passes_callable_token(self, mock_skyflow):
self.assertEqual(kwargs["base_url"], "https://test-vault-url.com")
self.assertTrue(callable(kwargs["token"]), "token must be a callable (lambda)")
- @patch("skyflow.vault.client.client.Skyflow")
+ @patch("skyflow.vault.client.client.SkyflowAuth")
def test_initialize_api_client_lambda_returns_cached_bearer_token(self, mock_skyflow):
"""Lambda returns _bearer_token when it is set (interceptor behaviour)."""
self.vault_client._bearer_token = "refreshed_token"
@@ -89,7 +89,7 @@ def test_initialize_api_client_lambda_returns_cached_bearer_token(self, mock_sky
_, kwargs = mock_skyflow.call_args
self.assertEqual(kwargs["token"](), "refreshed_token")
- @patch("skyflow.vault.client.client.Skyflow")
+ @patch("skyflow.vault.client.client.SkyflowAuth")
def test_initialize_api_client_lambda_falls_back_to_initial_token(self, mock_skyflow):
"""Lambda falls back to the initial token when _bearer_token is None."""
self.vault_client._bearer_token = None
@@ -114,13 +114,17 @@ def test_get_query_api(self):
self.vault_client._api_client = MagicMock()
self.assertIsNotNone(self.vault_client.get_query_api())
- def test_get_detect_text_api(self):
- self.vault_client._api_client = MagicMock()
- self.assertIsNotNone(self.vault_client.get_detect_text_api())
+ def test_get_strings_v2_api(self):
+ self.vault_client._detect_api_client = MagicMock()
+ self.assertIsNotNone(self.vault_client.get_strings_v2_api())
- def test_get_detect_file_api(self):
- self.vault_client._api_client = MagicMock()
- self.assertIsNotNone(self.vault_client.get_detect_file_api())
+ def test_get_files_v2_api(self):
+ self.vault_client._detect_api_client = MagicMock()
+ self.assertIsNotNone(self.vault_client.get_files_v2_api())
+
+ def test_get_guardrails_v2_api(self):
+ self.vault_client._detect_api_client = MagicMock()
+ self.assertIsNotNone(self.vault_client.get_guardrails_v2_api())
if __name__ == "__main__":
diff --git a/skyvault/tests/vault/controller/test__detect.py b/skyvault/tests/vault/controller/test__detect.py
deleted file mode 100644
index 9569961f..00000000
--- a/skyvault/tests/vault/controller/test__detect.py
+++ /dev/null
@@ -1,960 +0,0 @@
-import unittest
-from unittest.mock import Mock, patch, MagicMock
-import base64
-import os
-import tempfile
-from skyflow.error import SkyflowError
-from skyflow.generated.rest import WordCharacterCount, FileDataDeidentifyText, FileDataDeidentifyAudio, Format
-from skyflow.utils import SkyflowMessages
-from skyflow.vault.controller import Detect
-from skyflow.vault.detect import DeidentifyTextRequest, ReidentifyTextRequest, \
- TokenFormat, DateTransformation, Transformations, DeidentifyFileRequest, GetDetectRunRequest, \
- DeidentifyFileResponse, FileInput, Bleep
-from skyflow.utils.enums import DetectEntities, TokenType
-import io
-
-from skyflow.vault.detect._file import File
-from tests.vault.controller._request_assertions import assert_request
-
-VAULT_ID = "test_vault_id"
-
-class TestDetect(unittest.TestCase):
- def setUp(self):
- # Mock vault client
- self.vault_client = Mock()
- self.vault_client.get_vault_id.return_value = VAULT_ID
- self.vault_client.get_logger.return_value = Mock()
-
- # Create a Detect instance with the mock client
- self.detect = Detect(self.vault_client)
-
- @patch("skyflow.vault.controller._detect.validate_deidentify_text_request")
- @patch("skyflow.vault.controller._detect.parse_deidentify_text_response")
- def test_deidentify_text_success(self, mock_parse_response, mock_validate):
- # Mock API response
- mock_api_response = Mock()
- mock_api_response.data = {
- 'text': '[TOKEN_1] lives in [TOKEN_2]',
- 'entities': [
- {
- 'token': 'Token1',
- 'value': 'John',
- 'text_index': {'start': 0, 'end': 4},
- 'processed_index': {'start': 0, 'end': 8},
- 'entity': 'NAME',
- 'scores': {'confidence': 0.9}
- }
- ],
- 'wordCount': 4,
- 'charCount': 20
- }
-
- # Create request
- request = DeidentifyTextRequest(
- text="John lives in NYC",
- entities=[DetectEntities.NAME],
- token_format=TokenFormat(default=TokenType.ENTITY_ONLY)
- )
-
- # Mock detect API
- detect_api = self.vault_client.get_detect_text_api.return_value
- detect_api.deidentify_string.return_value = mock_api_response
-
- # Call deidentify_text
- response = self.detect.deidentify_text(request)
-
- # Assertions
- mock_validate.assert_called_once_with(self.vault_client.get_logger(), request)
- mock_parse_response.assert_called_once_with(mock_api_response)
-
- # Assert the text, entity list and token format reach the API
- assert_request(
- self,
- detect_api.deidentify_string,
- {
- "vault_id": VAULT_ID,
- "text": "John lives in NYC",
- "entity_types": [DetectEntities.NAME],
- "token_type": {
- "default": TokenType.ENTITY_ONLY,
- "entity_unq_counter": None,
- "entity_only": None,
- "vault_token": None
- },
- "allow_regex": None,
- "restrict_regex": None,
- "transformations": None
- }
- )
-
- @patch("skyflow.vault.controller._detect.validate_reidentify_text_request")
- @patch("skyflow.vault.controller._detect.parse_reidentify_text_response")
- def test_reidentify_text_success(self, mock_parse_response, mock_validate):
- # Mock API response
- mock_api_response = Mock()
- mock_api_response.data = {
- 'text': 'John lives in NYC'
- }
-
- # Create request - all three re-identification formats populated
- request = ReidentifyTextRequest(
- text="Token1 lives in Token2",
- redacted_entities=[DetectEntities.NAME],
- masked_entities=[DetectEntities.LOCATION],
- plain_text_entities=[DetectEntities.EMAIL_ADDRESS]
- )
-
- # Mock detect API
- detect_api = self.vault_client.get_detect_text_api.return_value
- detect_api.reidentify_string.return_value = mock_api_response
-
- # Call reidentify_text
- response = self.detect.reidentify_text(request)
-
- # Assertions
- mock_validate.assert_called_once_with(self.vault_client.get_logger(), request)
- mock_parse_response.assert_called_once_with(mock_api_response)
-
- # Assert each entity list lands on the right re-identification format
- assert_request(
- self,
- detect_api.reidentify_string,
- {
- "vault_id": VAULT_ID,
- "text": "Token1 lives in Token2",
- "format": Format(
- redacted=[DetectEntities.NAME],
- masked=[DetectEntities.LOCATION],
- plaintext=[DetectEntities.EMAIL_ADDRESS]
- )
- }
- )
-
- @patch("skyflow.vault.controller._detect.validate_deidentify_text_request")
- def test_deidentify_text_handles_generic_error(self, mock_validate):
- request = DeidentifyTextRequest(
- text="John lives in NYC",
- entities=[DetectEntities.NAME]
- )
- detect_api = self.vault_client.get_detect_text_api.return_value
- detect_api.deidentify_string.side_effect = Exception("Generic Error")
-
- with self.assertRaises(Exception):
- self.detect.deidentify_text(request)
-
- detect_api.deidentify_string.assert_called_once()
-
- @patch("skyflow.vault.controller._detect.validate_reidentify_text_request")
- def test_reidentify_text_handles_generic_error(self, mock_validate):
- request = ReidentifyTextRequest(
- text="Token1 lives in Token2",
- redacted_entities=[DetectEntities.NAME]
- )
- detect_api = self.vault_client.get_detect_text_api.return_value
- detect_api.reidentify_string.side_effect = Exception("Generic Error")
-
- with self.assertRaises(Exception):
- self.detect.reidentify_text(request)
-
- detect_api.reidentify_string.assert_called_once()
-
- @patch("skyflow.vault.controller._detect.validate_deidentify_file_request")
- @patch("skyflow.vault.controller._detect.base64")
- @patch("skyflow.vault.controller._detect.os.path.basename")
- @patch("skyflow.vault.controller._detect.open", create=True)
- def test_deidentify_file_txt_success(self, mock_open, mock_basename, mock_base64, mock_validate):
- file_content = b"test content"
- file_obj = Mock()
- file_obj.read.return_value = file_content
- file_obj.name = "/tmp/test.txt"
- mock_basename.return_value = "test.txt"
- mock_base64.b64encode.return_value = b"dGVzdCBjb250ZW50"
- req = DeidentifyFileRequest(file=FileInput(file=file_obj))
- req.entities = []
- req.token_format = Mock(default="default", entity_unique_counter=[], entity_only=[])
- req.allow_regex_list = []
- req.restrict_regex_list = []
- req.transformations = None
- req.output_directory = "/tmp"
- files_api = Mock()
- files_api.with_raw_response = files_api
- files_api.deidentify_text = Mock()
- self.vault_client.get_detect_file_api.return_value = files_api
- api_response = Mock()
- api_response.data = Mock(run_id="runid123")
- files_api.deidentify_text.return_value = api_response
-
- processed_response = Mock()
- processed_response.status = "SUCCESS"
- processed_response.output = []
- processed_response.word_character_count = WordCharacterCount(word_count=1, character_count=1)
- with patch.object(self.detect, "_Detect__poll_for_processed_file",
- return_value=processed_response) as mock_poll, \
- patch.object(self.detect, "_Detect__parse_deidentify_file_response",
- return_value=DeidentifyFileResponse(file_base64="dGVzdCBjb250ZW50",
- file=io.BytesIO(b"test content"), type="txt",
- extension="txt",
- word_count=1, char_count=1, size_in_kb=1,
- duration_in_seconds=None, page_count=None,
- slide_count=None, entities=[], run_id="runid123",
- status="SUCCESS")) as mock_parse:
- result = self.detect.deidentify_file(req)
-
- mock_validate.assert_called_once()
- mock_poll.assert_called_once()
- mock_parse.assert_called_once()
-
- # Assert the encoded file and detect options reach the txt endpoint
- assert_request(
- self,
- files_api.deidentify_text,
- {
- "vault_id": VAULT_ID,
- "file": FileDataDeidentifyText(base_64="dGVzdCBjb250ZW50", data_format="txt"),
- "entity_types": [],
- "token_type": {
- "default": req.token_format.default,
- "entity_unq_counter": req.token_format.entity_unique_counter,
- "entity_only": req.token_format.entity_only,
- "vault_token": req.token_format.vault_token
- },
- "allow_regex": [],
- "restrict_regex": [],
- "transformations": None
- }
- )
-
- self.assertIsInstance(result, DeidentifyFileResponse)
- self.assertEqual(result.status, "SUCCESS")
- self.assertEqual(result.run_id, "runid123")
- self.assertEqual(result.file_base64, "dGVzdCBjb250ZW50")
- self.assertEqual(result.type, "txt")
- self.assertEqual(result.extension, "txt")
-
- self.assertIsInstance(result.file, File)
- result.file.seek(0)
- self.assertEqual(result.file.read(), b"test content")
- self.assertEqual(result.word_count, 1)
- self.assertEqual(result.char_count, 1)
- self.assertEqual(result.size_in_kb, 1)
- self.assertIsNone(result.duration_in_seconds)
- self.assertIsNone(result.page_count)
- self.assertIsNone(result.slide_count)
- self.assertEqual(result.entities, [])
-
- @patch("skyflow.vault.controller._detect.validate_deidentify_file_request")
- @patch("skyflow.vault.controller._detect.base64")
- def test_deidentify_file_audio_success(self, mock_base64, mock_validate):
- file_content = b"audio bytes"
- file_obj = Mock()
- file_obj.read.return_value = file_content
- file_obj.name = "audio.mp3"
- mock_base64.b64encode.return_value = b"YXVkaW8gYnl0ZXM="
- bleep = Bleep(gain=0.5, frequency=800.0, start_padding=0.1, stop_padding=0.2)
- req = DeidentifyFileRequest(
- file=FileInput(file=file_obj),
- bleep=bleep,
- output_processed_audio=True
- )
- req.entities = []
- req.token_format = Mock(default="default", entity_unique_counter=[], entity_only=[])
- req.allow_regex_list = []
- req.restrict_regex_list = []
- req.transformations = None
- req.output_directory = None
- files_api = Mock()
- files_api.with_raw_response = files_api
- files_api.deidentify_audio = Mock()
- self.vault_client.get_detect_file_api.return_value = files_api
- api_response = Mock()
- api_response.data = Mock(run_id="runid456")
- files_api.deidentify_audio.return_value = api_response
-
- processed_response = Mock()
- processed_response.status = "SUCCESS"
- processed_response.output = []
- processed_response.word_character_count = Mock(word_count=1, character_count=1)
- with patch.object(self.detect, "_Detect__poll_for_processed_file",
- return_value=processed_response) as mock_poll, \
- patch.object(self.detect, "_Detect__parse_deidentify_file_response",
- return_value=DeidentifyFileResponse(file_base64="YXVkaW8gYnl0ZXM=",
- file=io.BytesIO(b"audio bytes"), type="mp3",
- extension="mp3",
- word_count=1, char_count=1, size_in_kb=1,
- duration_in_seconds=1, page_count=None,
- slide_count=None, entities=[], run_id="runid456",
- status="SUCCESS")) as mock_parse:
- result = self.detect.deidentify_file(req)
- mock_validate.assert_called_once()
- mock_poll.assert_called_once()
- mock_parse.assert_called_once()
-
- # Assert the audio-only options - bleep settings and transcription flags - are sent
- assert_request(
- self,
- files_api.deidentify_audio,
- {
- "vault_id": VAULT_ID,
- "file": FileDataDeidentifyAudio(base_64="YXVkaW8gYnl0ZXM=", data_format="mp3"),
- "entity_types": [],
- "token_type": {
- "default": req.token_format.default,
- "entity_unq_counter": req.token_format.entity_unique_counter,
- "entity_only": req.token_format.entity_only,
- "vault_token": req.token_format.vault_token
- },
- "allow_regex": [],
- "restrict_regex": [],
- "transformations": None,
- "output_transcription": None,
- "output_processed_audio": True,
- "bleep_gain": 0.5,
- "bleep_frequency": 800.0,
- "bleep_start_padding": 0.1,
- "bleep_stop_padding": 0.2
- }
- )
- self.assertIsInstance(result, DeidentifyFileResponse)
- self.assertEqual(result.status, "SUCCESS")
-
- @patch("skyflow.vault.controller._detect.validate_deidentify_file_request")
- def test_deidentify_file_exception(self, mock_validate):
- req = DeidentifyFileRequest(file=Mock())
- req.entities = []
- req.token_format = Mock(default="default", entity_unique_counter=[], entity_only=[])
- req.allow_regex_list = []
- req.restrict_regex_list = []
- req.transformations = None
- req.output_directory = None
- files_api = Mock()
- files_api.with_raw_response = files_api
- files_api.deidentify_text.side_effect = Exception("API Error")
- self.vault_client.get_detect_file_api.return_value = files_api
- with self.assertRaises(Exception):
- self.detect.deidentify_file(req)
-
- @patch("skyflow.vault.controller._detect.validate_get_detect_run_request")
- def test_get_detect_run_success(self, mock_validate):
- req = GetDetectRunRequest(run_id="runid789")
- files_api = Mock()
- files_api.with_raw_response = files_api
- files_api.get_run = Mock()
- self.vault_client.get_detect_file_api.return_value = files_api
- response = Mock()
- response.status = "SUCCESS"
- response.output = []
- response.wordCharacterCount = Mock(wordCount=1, characterCount=1)
- files_api.get_run.return_value = response
- with patch.object(self.detect, "_Detect__parse_deidentify_file_response",
- return_value=DeidentifyFileResponse(file="file", type="txt", extension="txt", word_count=1,
- char_count=1, size_in_kb=1, duration_in_seconds=None,
- page_count=None, slide_count=None, entities=[],
- run_id="runid789", status="SUCCESS")) as mock_parse:
- result = self.detect.get_detect_run(req)
- mock_validate.assert_called_once()
- mock_parse.assert_called_once()
-
- # Assert the run id is the one looked up
- assert_request(
- self,
- files_api.get_run,
- {"vault_id": VAULT_ID},
- expected_args=("runid789",)
- )
- self.assertIsInstance(result, DeidentifyFileResponse)
- self.assertEqual(result.status, "SUCCESS")
-
- @patch("skyflow.vault.controller._detect.validate_get_detect_run_request")
- def test_get_detect_run_exception(self, mock_validate):
- req = GetDetectRunRequest(run_id="runid789")
- files_api = Mock()
- files_api.with_raw_response = files_api
- files_api.get_run.side_effect = Exception("API Error")
- self.vault_client.get_detect_file_api.return_value = files_api
- with self.assertRaises(Exception):
- self.detect.get_detect_run(req)
-
- @patch("skyflow.vault.controller._detect.validate_deidentify_file_request")
- @patch("skyflow.vault.controller._detect.base64")
- @patch("skyflow.vault.controller._detect.os.path.basename")
- @patch("skyflow.vault.controller._detect.open", create=True)
- @patch.object(Detect, "_Detect__poll_for_processed_file")
- def test_deidentify_file_all_branches(self, mock_poll, mock_open, mock_basename, mock_base64, mock_validate):
- # Common mocks
- file_content = b"test content"
- mock_base64.b64encode.return_value = b"dGVzdCBjb250ZW50"
- mock_base64.b64decode.return_value = file_content
-
- # Prepare a generic processed_response for all branches
- processed_response = Mock()
- processed_response.status = "SUCCESS"
- processed_response.output = [
- {"processed_file": "dGVzdCBjb250ZW50", "processed_file_type": "pdf", "processed_file_extension": "pdf"}
- ]
- processed_response.size = 1
- processed_response.duration = 1
- processed_response.pages = 1
- processed_response.slides = 1
- processed_response.message = ""
- processed_response.run_id = "runid123"
- processed_response.word_character_count = WordCharacterCount(word_count=1, character_count=1)
- mock_poll.return_value = processed_response
-
- # Test configuration for different file types
- test_cases = [
- ("test.pdf", "pdf", "deidentify_pdf"),
- ("test.jpg", "jpg", "deidentify_image"),
- ("test.pptx", "pptx", "deidentify_presentation"),
- ("test.csv", "csv", "deidentify_spreadsheet"),
- ("test.docx", "docx", "deidentify_document"),
- ("test.json", "json", "deidentify_structured_text"),
- ("test.xml", "xml", "deidentify_structured_text"),
- ("test.unknown", "unknown", "deidentify_file")
- ]
-
- for file_name, extension, api_method in test_cases:
- with self.subTest(file_type=extension):
- # Setup file mock
- file_obj = Mock()
- file_obj.read.return_value = file_content
- file_obj.name = file_name
- mock_basename.return_value = file_name
-
- # Setup request with FileInput
- req = DeidentifyFileRequest(file=FileInput(file=file_obj))
- req.entities = []
- req.token_format = Mock(default="default", entity_unique_counter=[], entity_only=[])
- req.allow_regex_list = []
- req.restrict_regex_list = []
- req.transformations = None
- req.output_directory = "/tmp"
-
- # Setup API mock
- files_api = Mock()
- files_api.with_raw_response = files_api
- api_method_mock = Mock()
- setattr(files_api, api_method, api_method_mock)
- self.vault_client.get_detect_file_api.return_value = files_api
-
- # Setup API response
- api_response = Mock()
- api_response.data = Mock(run_id="runid123")
- api_method_mock.return_value = api_response
-
- # Actually run the method
- result = self.detect.deidentify_file(req)
-
- # Verify the result
- print("Result : ", result)
- self.assertIsInstance(result, DeidentifyFileResponse)
- self.assertEqual(result.status, "SUCCESS")
- self.assertEqual(result.run_id, "runid123")
- self.assertEqual(result.file_base64, "dGVzdCBjb250ZW50")
- self.assertIsInstance(result.file, File)
- result.file.seek(0) # Reset file pointer before reading
- self.assertEqual(result.file.read(), b"test content")
- self.assertEqual(result.type, "pdf")
- self.assertEqual(result.extension, "pdf")
- self.assertEqual(result.size_in_kb, 1)
- self.assertEqual(result.duration_in_seconds, 1)
- self.assertEqual(result.page_count, 1)
- self.assertEqual(result.slide_count, 1)
- self.assertEqual(result.word_count, 1)
- self.assertEqual(result.char_count, 1)
-
- # Verify API was called
- api_method_mock.assert_called_once()
- mock_poll.assert_called_with("runid123", None)
-
- @patch("skyflow.vault.controller._detect.validate_deidentify_file_request")
- @patch("skyflow.vault.controller._detect.base64")
- def test_deidentify_file_exception(self, mock_base64, mock_validate):
- file_obj = Mock()
- file_obj.read.side_effect = Exception("Read error")
- file_obj.name = "test.txt"
- req = DeidentifyFileRequest(file=FileInput(file=file_obj))
- req.entities = []
- req.token_format = Mock(default="default", entity_unique_counter=[], entity_only=[])
- req.allow_regex_list = []
- req.restrict_regex_list = []
- req.transformations = None
- req.output_directory = None
- with self.assertRaises(Exception):
- self.detect.deidentify_file(req)
-
- @patch("skyflow.vault.controller._detect.time.sleep", return_value=None)
- def test_poll_for_processed_file_success(self, mock_sleep):
- files_api = Mock()
- files_api.with_raw_response = files_api
- self.vault_client.get_detect_file_api.return_value = files_api
-
- call_count = {"count": 0}
-
- def get_run_side_effect(*args, **kwargs):
- if call_count["count"] < 1:
- call_count["count"] += 1
- in_progress = Mock()
- in_progress.status = "IN_PROGRESS"
- in_progress.message = ""
- return Mock(data=in_progress)
- else:
- success = Mock()
- success.status = "SUCCESS"
- return Mock(data=success)
-
- files_api.get_run.side_effect = get_run_side_effect
-
- # Use max_wait_time > 1 to allow the loop to reach the SUCCESS status
- result = self.detect._Detect__poll_for_processed_file("runid123", max_wait_time=2)
- self.assertEqual(result.status, "SUCCESS")
-
- @patch("skyflow.vault.controller._detect.time.sleep", return_value=None)
- def test_poll_for_processed_file_failed(self, mock_sleep):
- files_api = Mock()
- files_api.with_raw_response = files_api
- self.vault_client.get_detect_file_api.return_value = files_api
-
- # Always return FAILED on first call
- def get_run_side_effect(*args, **kwargs):
- failed = Mock()
- failed.status = "FAILED"
- failed.message = "fail"
- return Mock(data=failed)
-
- files_api.get_run.side_effect = get_run_side_effect
-
- result = self.detect._Detect__poll_for_processed_file("runid123", max_wait_time=1)
- self.assertEqual(result.status, "FAILED")
- self.assertEqual(result.message, "fail")
-
- def test_parse_deidentify_file_response_dict_and_obj(self):
- # Dict input
- data = {
- "output": [
- {"processedFile": "YWJj", "processedFileType": "pdf", "processedFileExtension": "pdf"}, # base64 for "abc"
- {"processedFile": "ZGVm", "processedFileType": "entities", "processedFileExtension": "json"} # base64 for "def"
- ],
- "wordCharacterCount": {"wordCount": 5, "characterCount": 10},
- "size": 1,
- "duration": 2,
- "pages": 3,
- "slides": 4,
- "run_id": "runid",
- "status": "SUCCESS"
- }
- result = self.detect._Detect__parse_deidentify_file_response(data, "runid", "SUCCESS")
- self.assertIsInstance(result, DeidentifyFileResponse)
-
- # Object input
- class DummyWordChar:
- wordCount = 7
- characterCount = 14
-
- class DummyData:
- output = [
- type("O", (),
- {"processed_file": "YWJj", "processed_file_type": "pdf", "processed_file_extension": "pdf"})(),
- type("O", (),
- {"processed_file": "ZGVm", "processed_file_type": "entities", "processed_file_extension": "json"})()
- ]
- word_character_count = DummyWordChar()
- size = 1
- duration = 2
- pages = 3
- slides = 4
- run_id = "runid"
- status = "SUCCESS"
-
- obj_data = DummyData()
- result = self.detect._Detect__parse_deidentify_file_response(obj_data, "runid", "SUCCESS")
- self.assertIsInstance(result, DeidentifyFileResponse)
- self.assertEqual(result.file_base64, "YWJj")
- self.assertIsInstance(result.file, File)
- self.assertEqual(result.file.read(), b"abc")
- def test_get_token_format_missing_attribute(self):
- """Test __get_token_format when token_format attribute is missing"""
- class DummyRequest:
- pass
- request = DummyRequest()
- result = self.detect._Detect__get_token_format(request)
- self.assertIsNone(result)
-
- def test_get_transformations_missing_shift_dates(self):
- """Test __get_transformations when shift_dates is None"""
- class DummyTransformations:
- shift_dates = None
- class DummyRequest:
- transformations = DummyTransformations()
- request = DummyRequest()
- result = self.detect._Detect__get_transformations(request)
- self.assertIsNone(result)
-
- @patch("skyflow.vault.controller._detect.validate_get_detect_run_request")
- def test_get_detect_run_in_progress_status(self, mock_validate):
- """Test get_detect_run when status is IN_PROGRESS"""
- # Setup
- run_id = "test_run_id"
- req = GetDetectRunRequest(run_id=run_id)
-
- # Mock API response
- files_api = Mock()
- files_api.with_raw_response = files_api
- mock_response = Mock()
- mock_response.data = Mock()
- mock_response.data.status = 'IN_PROGRESS'
- files_api.get_run.return_value = mock_response
-
- self.vault_client.get_detect_file_api.return_value = files_api
-
- # Execute — IN_PROGRESS is returned directly without going through the parser
- result = self.detect.get_detect_run(req)
-
- self.assertIsInstance(result, DeidentifyFileResponse)
- self.assertEqual(result.status, 'IN_PROGRESS')
- self.assertEqual(result.run_id, run_id)
-
- def test_get_transformations_with_shift_dates(self):
-
- class DummyShiftDates:
- max = 30
- min = 10
- entities = ["SSN"]
-
- class DummyTransformations:
- shift_dates = DummyShiftDates()
-
- class DummyRequest:
- transformations = DummyTransformations()
-
- request = DummyRequest()
- result = self.detect._Detect__get_transformations(request)
-
- self.assertEqual(result, {
- 'shift_dates': {
- 'max_days': 30,
- 'min_days': 10,
- 'entity_types': ["SSN"]
- }
- })
-
- @patch("skyflow.vault.controller._detect.time.sleep", return_value=None)
- def test_poll_for_processed_file_timeout(self, mock_sleep):
- """Test polling timeout returns IN_PROGRESS status"""
- files_api = Mock()
- files_api.with_raw_response = files_api
- self.vault_client.get_detect_file_api.return_value = files_api
-
- # Always return IN_PROGRESS
- def get_run_side_effect(*args, **kwargs):
- in_progress = Mock()
- in_progress.status = "IN_PROGRESS"
- return Mock(data=in_progress)
-
- files_api.get_run.side_effect = get_run_side_effect
-
- result = self.detect._Detect__poll_for_processed_file("runid123", max_wait_time=1)
- self.assertIsInstance(result, DeidentifyFileResponse)
- self.assertEqual(result.status, "IN_PROGRESS")
- self.assertEqual(result.run_id, "runid123")
-
- @patch("skyflow.vault.controller._detect.time.sleep", return_value=None)
- def test_poll_for_processed_file_wait_time_calculation(self, mock_sleep):
- """Test wait time calculation in polling loop"""
- files_api = Mock()
- files_api.with_raw_response = files_api
- self.vault_client.get_detect_file_api.return_value = files_api
-
- calls = []
-
- def track_sleep(*args):
- calls.append(args[0]) # Record wait time
-
- mock_sleep.side_effect = track_sleep
-
- # Return IN_PROGRESS twice then SUCCESS
- responses = [
- Mock(data=Mock(status="IN_PROGRESS")),
- Mock(data=Mock(status="IN_PROGRESS")),
- Mock(data=Mock(status="SUCCESS"))
- ]
- files_api.get_run.side_effect = responses
-
- result = self.detect._Detect__poll_for_processed_file("runid123", max_wait_time=4)
-
- self.assertEqual(calls, [2, 2])
- self.assertEqual(result.status, "SUCCESS")
-
- def test_parse_deidentify_file_response_output_conversion(self):
- """Test output conversion in parse_deidentify_file_response"""
-
- class OutputObj:
- processed_file = "YWJjMTIz" # base64 for "abc123"
- processed_file_type = "pdf"
- processed_file_extension = "pdf"
-
- data = Mock()
- data.output = [OutputObj()]
- data.size = 1
- data.wordCharacterCount = Mock(wordCount=1, characterCount=1)
-
- result = self.detect._Detect__parse_deidentify_file_response(data)
-
- # Check base64 string
- self.assertEqual(result.file_base64, "YWJjMTIz")
- # Check File object
- self.assertIsInstance(result.file, File)
- self.assertEqual(result.file.read(), b"abc123")
- # Check other attributes
- self.assertEqual(result.type, "pdf")
- self.assertEqual(result.extension, "pdf")
- # Reset file pointer and verify content again
- result.file.seek(0)
- self.assertEqual(result.file.read(), b"abc123")
-
- @patch("skyflow.vault.controller._detect.validate_deidentify_file_request")
- @patch("skyflow.vault.controller._detect.base64")
- @patch("skyflow.vault.controller._detect.os.path.basename")
- @patch("skyflow.vault.controller._detect.open", create=True)
- def test_deidentify_file_using_file_path(self, mock_open, mock_basename, mock_base64, mock_validate):
- # Setup mock file context
- mock_file = MagicMock()
- mock_file.read.return_value = b"test content from file path"
- mock_file.name = "/path/to/test.txt"
- mock_file.__enter__.return_value = mock_file # Mock context manager
- mock_open.return_value = mock_file
- mock_basename.return_value = "test.txt"
- mock_base64.b64encode.return_value = b"dGVzdCBjb250ZW50IGZyb20gZmlsZSBwYXRo" # base64 of "test content from file path"
- mock_base64.b64decode.return_value = b"test content from file path"
- # Create request with file_path
- req = DeidentifyFileRequest(file=FileInput(file_path="/path/to/test.txt"))
- req.entities = []
- req.token_format = Mock(default="default", entity_unique_counter=[], entity_only=[])
- req.allow_regex_list = []
- req.restrict_regex_list = []
- req.transformations = None
- req.output_directory = "/tmp"
-
- # Setup API mock
- files_api = Mock()
- files_api.with_raw_response = files_api
- files_api.deidentify_text = Mock()
- self.vault_client.get_detect_file_api.return_value = files_api
- api_response = Mock()
- api_response.data = Mock(run_id="runid123")
- files_api.deidentify_text.return_value = api_response
-
- # Setup processed response
- processed_response = Mock()
- processed_response.status = "SUCCESS"
- processed_response.output = [
- Mock(processedFile="dGVzdCBjb250ZW",
- processedFileType="txt",
- processedFileExtension="txt")
- ]
- processed_response.word_character_count = WordCharacterCount(word_count=1, character_count=1)
-
- # Test the method
- with patch.object(self.detect, "_Detect__poll_for_processed_file",
- return_value=processed_response) as mock_poll, \
- patch.object(self.detect, "_Detect__parse_deidentify_file_response",
- return_value=DeidentifyFileResponse(
- file_base64="dGVzdCBjb250ZW50IGZyb20gZmlsZSBwYXRo",
- file=io.BytesIO(b"test content from file path"),
- type="txt",
- extension="txt",
- word_count=1,
- char_count=1,
- size_in_kb=1,
- duration_in_seconds=None,
- page_count=None,
- slide_count=None,
- entities=[],
- run_id="runid123",
- status="SUCCESS",
- )) as mock_parse:
-
- result = self.detect.deidentify_file(req)
-
- mock_file.read.assert_called_once()
- mock_validate.assert_called_once()
- mock_basename.assert_called_with("/path/to/test.txt")
- # The file_path branch encodes the file read off disk, same shape as file_object
- assert_request(
- self,
- files_api.deidentify_text,
- {
- "vault_id": VAULT_ID,
- "file": FileDataDeidentifyText(
- base_64="dGVzdCBjb250ZW50IGZyb20gZmlsZSBwYXRo",
- data_format="txt"
- ),
- "entity_types": [],
- "token_type": {
- "default": req.token_format.default,
- "entity_unq_counter": req.token_format.entity_unique_counter,
- "entity_only": req.token_format.entity_only,
- "vault_token": req.token_format.vault_token
- },
- "allow_regex": [],
- "restrict_regex": [],
- "transformations": None
- }
- )
- mock_poll.assert_called_once()
- mock_parse.assert_called_once()
-
- # Response assertions
- self.assertIsInstance(result, DeidentifyFileResponse)
- self.assertEqual(result.status, "SUCCESS")
- self.assertEqual(result.run_id, "runid123")
- self.assertEqual(result.file_base64, "dGVzdCBjb250ZW50IGZyb20gZmlsZSBwYXRo")
- self.assertEqual(result.type, "txt")
- self.assertEqual(result.extension, "txt")
-
- self.assertIsInstance(result.file, File)
- result.file.seek(0)
- self.assertEqual(result.file.read(), b"test content from file path")
- self.assertEqual(result.word_count, 1)
- self.assertEqual(result.char_count, 1)
- self.assertEqual(result.size_in_kb, 1)
- self.assertIsNone(result.duration_in_seconds)
- self.assertIsNone(result.page_count)
- self.assertIsNone(result.slide_count)
- self.assertEqual(result.entities, [])
-
- def test_poll_for_processed_file_exception(self):
- files_api = Mock()
- files_api.with_raw_response = files_api
- files_api.get_run.side_effect = Exception("poll error")
- self.vault_client.get_detect_file_api.return_value = files_api
- with self.assertRaises(Exception):
- self.detect._Detect__poll_for_processed_file("runid", max_wait_time=5)
-
- def test_save_output_directory_not_exists(self):
- output = Mock()
- output.processedFile = base64.b64encode(b"data").decode()
- output.processedFileType = "redacted_file"
- output.processedFileExtension = "txt"
- response = Mock()
- response.output = [output]
- with patch("skyflow.vault.controller._detect.os.path.exists", return_value=False):
- self.detect._Detect__save_deidentify_file_response_output(
- response, "/nonexistent_dir", "file.txt", "file"
- )
-
- def test_save_output_second_non_redacted_item(self):
- with tempfile.TemporaryDirectory() as tmp_dir:
- output1 = Mock()
- output1.processedFile = base64.b64encode(b"data1").decode()
- output1.processedFileType = "redacted_file"
- output1.processedFileExtension = "txt"
- output2 = Mock()
- output2.processedFile = base64.b64encode(b"data2").decode()
- output2.processedFileType = "entities"
- output2.processedFileExtension = "json"
- response = Mock()
- response.output = [output1, output2]
- self.detect._Detect__save_deidentify_file_response_output(
- response, tmp_dir, "original.txt", "original"
- )
-
- def test_save_output_path_traversal_blocked(self):
- output = Mock()
- output.processedFile = base64.b64encode(b"data").decode()
- output.processedFileType = "redacted_file"
- output.processedFileExtension = "txt"
- response = Mock()
- response.output = [output]
- call_count = [0]
-
- def fake_realpath(p):
- call_count[0] += 1
- if call_count[0] == 1:
- return "/safe_dir"
- return "/outside/path"
-
- with patch("skyflow.vault.controller._detect.os.path.exists", return_value=True), \
- patch("skyflow.vault.controller._detect.os.path.realpath", side_effect=fake_realpath):
- self.detect._Detect__save_deidentify_file_response_output(
- response, "/safe_dir", "file.txt", "file"
- )
-
- def test_save_output_write_exception(self):
- with tempfile.TemporaryDirectory() as tmp_dir:
- output = Mock()
- output.processedFile = base64.b64encode(b"data").decode()
- output.processedFileType = "redacted_file"
- output.processedFileExtension = "txt"
- response = Mock()
- response.output = [output]
- with patch("skyflow.vault.controller._detect.base64.b64decode",
- side_effect=Exception("decode error")), \
- self.assertRaises(Exception):
- self.detect._Detect__save_deidentify_file_response_output(
- response, tmp_dir, "file.txt", "file"
- )
-
- def test_save_output_no_file_extension_uses_original_name(self):
- """Branches 113->117 and 119->124: processed_file_extension is falsy — safe_ext stays None."""
- with tempfile.TemporaryDirectory() as tmp_dir:
- output = Mock()
- output.processedFile = base64.b64encode(b"data").decode()
- output.processedFileType = "redacted_file"
- output.processedFileExtension = None
- output.processed_file_extension = None
- response = Mock()
- response.output = [output]
- self.detect._Detect__save_deidentify_file_response_output(
- response, tmp_dir, "original.txt", "original"
- )
-
- @patch("skyflow.vault.controller._detect.time.sleep", return_value=None)
- def test_poll_unknown_status_then_success(self, mock_sleep):
- """Branch 80->65: status is unknown, loops back, then returns SUCCESS."""
- files_api = Mock()
- files_api.with_raw_response = files_api
- self.vault_client.get_detect_file_api.return_value = files_api
-
- call_count = {"n": 0}
-
- def side_effect(*args, **kwargs):
- call_count["n"] += 1
- r = Mock()
- if call_count["n"] == 1:
- r.status = "UNKNOWN_STATUS"
- else:
- r.status = "SUCCESS"
- return Mock(data=r)
-
- files_api.get_run.side_effect = side_effect
- result = self.detect._Detect__poll_for_processed_file("runid", max_wait_time=10)
- self.assertEqual(result.status, "SUCCESS")
-
- def test_get_file_from_request_no_file_no_path_returns_none(self):
- """Branch 285->exit: file_input has neither file nor file_path set."""
- req = DeidentifyFileRequest(file=FileInput(file=None, file_path=None))
- result = self.detect._Detect__get_file_from_request(req)
- self.assertIsNone(result)
-
- @patch("skyflow.vault.controller._detect.validate_deidentify_file_request")
- @patch("skyflow.vault.controller._detect.base64")
- def test_deidentify_file_api_error_inside_try(self, mock_base64, mock_validate):
- file_content = b"test content"
- file_obj = Mock()
- file_obj.read.return_value = file_content
- file_obj.name = "test.txt"
- mock_base64.b64encode.return_value.decode.return_value = "encoded"
- req = DeidentifyFileRequest(file=FileInput(file=file_obj))
- req.entities = []
- req.token_format = None
- req.allow_regex_list = []
- req.restrict_regex_list = []
- req.transformations = None
- req.output_directory = None
- req.wait_time = None
- files_api = Mock()
- files_api.with_raw_response = files_api
- files_api.deidentify_text.side_effect = Exception("API error inside try")
- self.vault_client.get_detect_file_api.return_value = files_api
- with self.assertRaises(Exception):
- self.detect.deidentify_file(req)
diff --git a/skyvault/tests/vault/controller/test__vault.py b/skyvault/tests/vault/controller/test__vault.py
index be7c82fe..139d4fbb 100644
--- a/skyvault/tests/vault/controller/test__vault.py
+++ b/skyvault/tests/vault/controller/test__vault.py
@@ -1,6 +1,6 @@
import unittest
from unittest.mock import Mock, patch, mock_open as mock_open_func, mock_open
-from skyflow.generated.rest import V1BatchRecord, V1FieldRecords, V1DetokenizeRecordRequest, V1TokenizeRecordRequest
+from skyflow.generated.rest import BatchRecord, FieldRecords, DetokenizeRecordRequest, TokenizeRecordRequest
from skyflow.utils._skyflow_messages import SkyflowMessages
from skyflow.utils.enums import RedactionType, TokenMode
from skyflow.vault.controller import Vault
@@ -40,7 +40,7 @@ def test_insert_with_continue_on_error(self, mock_parse_response, mock_validate)
)
expected_body = [
- V1BatchRecord(
+ BatchRecord(
fields={"field": "value"},
table_name=TABLE_NAME,
method="POST",
@@ -70,7 +70,7 @@ def test_insert_with_continue_on_error(self, mock_parse_response, mock_validate)
# Set the return value for the parse response
mock_parse_response.return_value = expected_response
records_api = self.vault_client.get_records_api.return_value
- records_api.with_raw_response.record_service_batch_operation.return_value = mock_api_response
+ records_api.with_raw_response.batch_operation.return_value = mock_api_response
# Call the insert function
result = self.vault.insert(request)
@@ -82,11 +82,10 @@ def test_insert_with_continue_on_error(self, mock_parse_response, mock_validate)
# Assert the request built for the API matches the expected batch body
assert_request(
self,
- records_api.with_raw_response.record_service_batch_operation,
+ records_api.with_raw_response.batch_operation,
{
"records": expected_body,
- "continue_on_error": True,
- "byot": request.token_mode.value
+ "continue_on_error": True
},
expected_args=(VAULT_ID,)
)
@@ -113,7 +112,7 @@ def test_insert_with_continue_on_error_false(self, mock_parse_response, mock_val
# Expected API request body based on InsertRequest parameters
expected_body = [
- V1FieldRecords(fields={"field": "value"})
+ FieldRecords(fields={"field": "value"})
]
# Mock API response for a successful insert
@@ -127,7 +126,7 @@ def test_insert_with_continue_on_error_false(self, mock_parse_response, mock_val
# Set the return value for the parse response
mock_parse_response.return_value = expected_response
records_api = self.vault_client.get_records_api.return_value
- records_api.with_raw_response.record_service_insert_record.return_value = mock_api_response
+ records_api.with_raw_response.insert_records.return_value = mock_api_response
# Call the insert function
result = self.vault.insert(request)
@@ -139,7 +138,7 @@ def test_insert_with_continue_on_error_false(self, mock_parse_response, mock_val
# Assert the request built for the API matches the expected bulk body
assert_request(
self,
- records_api.with_raw_response.record_service_insert_record,
+ records_api.with_raw_response.insert_records,
{
"records": expected_body,
"tokenization": request.return_tokens,
@@ -160,12 +159,12 @@ def test_insert_handles_generic_error(self, mock_validate):
upsert=False,
homogeneous=False, continue_on_error=False, token_mode=Mock())
records_api = self.vault_client.get_records_api.return_value
- records_api.record_service_insert_record.side_effect = Exception("Generic Exception")
+ records_api.insert_records.side_effect = Exception("Generic Exception")
with self.assertRaises(Exception):
self.vault.insert(request)
- records_api.with_raw_response.record_service_insert_record.assert_called_once()
+ records_api.with_raw_response.insert_records.assert_called_once()
@patch("skyflow.vault.controller._vault.validate_insert_request")
def test_insert_raises_on_empty_key(self, mock_validate):
@@ -176,7 +175,7 @@ def test_insert_raises_on_empty_key(self, mock_validate):
with self.assertRaises(SkyflowError):
self.vault.insert(request)
- self.vault_client.get_records_api.return_value.with_raw_response.record_service_insert_record.assert_not_called()
+ self.vault_client.get_records_api.return_value.with_raw_response.insert_records.assert_not_called()
@patch("skyflow.vault.controller._vault.validate_insert_request")
@patch("skyflow.vault.controller._vault.parse_insert_response")
@@ -186,11 +185,11 @@ def test_insert_allows_empty_value(self, mock_parse_response, mock_validate):
mock_api_response = Mock()
mock_parse_response.return_value = InsertResponse(inserted_fields=[{"skyflow_id": "id1"}])
records_api = self.vault_client.get_records_api.return_value
- records_api.with_raw_response.record_service_insert_record.return_value = mock_api_response
+ records_api.with_raw_response.insert_records.return_value = mock_api_response
self.vault.insert(request)
- records_api.with_raw_response.record_service_insert_record.assert_called_once()
+ records_api.with_raw_response.insert_records.assert_called_once()
@patch("skyflow.vault.controller._vault.validate_insert_request")
@patch("skyflow.vault.controller._vault.parse_insert_response")
@@ -210,7 +209,7 @@ def test_insert_with_continue_on_error_false_when_tokens_are_not_none(self, mock
# Expected API request body based on InsertRequest parameters
expected_body = [
- V1FieldRecords(fields={"field": "value"}, tokens={"token_field": "token_val1"})
+ FieldRecords(fields={"field": "value"}, tokens={"token_field": "token_val1"})
]
# Mock API response for a successful insert
@@ -224,7 +223,7 @@ def test_insert_with_continue_on_error_false_when_tokens_are_not_none(self, mock
# Set the return value for the parse response
mock_parse_response.return_value = expected_response
records_api = self.vault_client.get_records_api.return_value
- records_api.with_raw_response.record_service_insert_record.return_value = mock_api_response
+ records_api.with_raw_response.insert_records.return_value = mock_api_response
# Call the insert function
result = self.vault.insert(request)
@@ -236,7 +235,7 @@ def test_insert_with_continue_on_error_false_when_tokens_are_not_none(self, mock
# Assert the request built for the API matches the expected bulk body
assert_request(
self,
- records_api.with_raw_response.record_service_insert_record,
+ records_api.with_raw_response.insert_records,
{
"records": expected_body,
"tokenization": request.return_tokens,
@@ -266,7 +265,7 @@ def test_update_successful(self, mock_parse_response, mock_validate):
)
# Expected payload
- expected_record = V1FieldRecords(fields={"field": "new_value"}, tokens=None)
+ expected_record = FieldRecords(fields={"field": "new_value"}, tokens=None)
# Mock API response
mock_api_response = Mock()
@@ -280,7 +279,7 @@ def test_update_successful(self, mock_parse_response, mock_validate):
# Set the return value for the parse response
mock_parse_response.return_value = expected_response
records_api = self.vault_client.get_records_api.return_value
- records_api.record_service_update_record.return_value = mock_api_response
+ records_api.update_record.return_value = mock_api_response
# Call the update function
result = self.vault.update(request)
@@ -292,7 +291,7 @@ def test_update_successful(self, mock_parse_response, mock_validate):
# Assert the request built for the API strips skyflow_id out of the record fields
assert_request(
self,
- records_api.record_service_update_record,
+ records_api.update_record,
{
"id": "12345",
"record": expected_record,
@@ -311,12 +310,12 @@ def test_update_handles_generic_error(self, mock_validate):
request = UpdateRequest(table="test_table", data={"skyflow_id": "123", "field": "value"},
return_tokens=False)
records_api = self.vault_client.get_records_api.return_value
- records_api.record_service_update_record.side_effect = Exception("Generic Exception")
+ records_api.update_record.side_effect = Exception("Generic Exception")
with self.assertRaises(Exception):
self.vault.update(request)
- records_api.record_service_update_record.assert_called_once()
+ records_api.update_record.assert_called_once()
@patch("skyflow.vault.controller._vault.validate_delete_request")
@patch("skyflow.vault.controller._vault.parse_delete_response")
@@ -343,7 +342,7 @@ def test_delete_successful(self, mock_parse_response, mock_validate):
# Set the return value for the parse response
mock_parse_response.return_value = expected_response
records_api = self.vault_client.get_records_api.return_value
- records_api.record_service_bulk_delete_record.return_value = mock_api_response
+ records_api.delete_records.return_value = mock_api_response
# Call the delete function
result = self.vault.delete(request)
@@ -355,7 +354,7 @@ def test_delete_successful(self, mock_parse_response, mock_validate):
# Assert the request built for the API carries the ids to delete
assert_request(
self,
- records_api.record_service_bulk_delete_record,
+ records_api.delete_records,
{"skyflow_ids": expected_payload},
expected_args=(VAULT_ID, TABLE_NAME)
)
@@ -368,12 +367,12 @@ def test_delete_successful(self, mock_parse_response, mock_validate):
def test_delete_handles_generic_exception(self, mock_validate):
request = DeleteRequest(table="test_table", ids=["id1", "id2"])
records_api = self.vault_client.get_records_api.return_value
- records_api.record_service_bulk_delete_record.side_effect = Exception("Generic Error")
+ records_api.delete_records.side_effect = Exception("Generic Error")
with self.assertRaises(Exception):
self.vault.delete(request)
- records_api.record_service_bulk_delete_record.assert_called_once()
+ records_api.delete_records.assert_called_once()
@patch("skyflow.vault.controller._vault.validate_get_request")
@patch("skyflow.vault.controller._vault.parse_get_response")
@@ -424,7 +423,7 @@ def test_get_successful(self, mock_parse_response, mock_validate):
# Set the return value for parse_get_response
mock_parse_response.return_value = expected_response
records_api = self.vault_client.get_records_api.return_value
- records_api.record_service_bulk_get_record.return_value = mock_api_response
+ records_api.get_records.return_value = mock_api_response
# Call the get function
result = self.vault.get(request)
@@ -436,7 +435,7 @@ def test_get_successful(self, mock_parse_response, mock_validate):
# Assert the request built for the API carries every get parameter
assert_request(
self,
- records_api.record_service_bulk_get_record,
+ records_api.get_records,
expected_payload,
expected_args=(VAULT_ID,)
)
@@ -489,7 +488,7 @@ def test_get_successful_with_column_values(self, mock_parse_response, mock_valid
# Set the return value for parse_get_response
mock_parse_response.return_value = expected_response
records_api = self.vault_client.get_records_api.return_value
- records_api.record_service_bulk_get_record.return_value = mock_api_response
+ records_api.get_records.return_value = mock_api_response
# Call the get function
result = self.vault.get(request)
@@ -499,7 +498,7 @@ def test_get_successful_with_column_values(self, mock_parse_response, mock_valid
# Assert the request built for the API looks the record up by column, not by id
assert_request(
self,
- records_api.record_service_bulk_get_record,
+ records_api.get_records,
expected_payload,
expected_args=(VAULT_ID,)
)
@@ -512,12 +511,12 @@ def test_get_successful_with_column_values(self, mock_parse_response, mock_valid
def test_get_handles_generic_error(self, mock_validate):
request = GetRequest(table="test_table", ids=["id1", "id2"])
records_api = self.vault_client.get_records_api.return_value
- records_api.record_service_bulk_get_record.side_effect = Exception("Generic Exception")
+ records_api.get_records.side_effect = Exception("Generic Exception")
with self.assertRaises(Exception):
self.vault.get(request)
- records_api.record_service_bulk_get_record.assert_called_once()
+ records_api.get_records.assert_called_once()
@patch("skyflow.vault.controller._vault.validate_query_request")
@patch("skyflow.vault.controller._vault.parse_query_response")
@@ -545,7 +544,7 @@ def test_query_successful(self, mock_parse_response, mock_validate):
# Set the return value for parse_query_response
mock_parse_response.return_value = expected_response
query_api = self.vault_client.get_query_api.return_value
- query_api.query_service_execute_query.return_value = mock_api_response
+ query_api.execute_query.return_value = mock_api_response
# Call the query function
result = self.vault.query(request)
@@ -556,7 +555,7 @@ def test_query_successful(self, mock_parse_response, mock_validate):
# Assert the query string reaches the API unaltered
assert_request(
self,
- query_api.query_service_execute_query,
+ query_api.execute_query,
{"query": "SELECT * FROM test_table"},
expected_args=(VAULT_ID,)
)
@@ -570,22 +569,22 @@ def test_query_successful(self, mock_parse_response, mock_validate):
def test_request_carries_sky_metadata_header(self, mock_parse_response, mock_validate):
"""Every controller call attaches the sky-metadata header naming this SDK version."""
query_api = self.vault_client.get_query_api.return_value
- query_api.query_service_execute_query.return_value = Mock()
+ query_api.execute_query.return_value = Mock()
self.vault.query(QueryRequest(query="SELECT * FROM test_table"))
- assert_sky_metadata(self, request_options_headers(query_api.query_service_execute_query))
+ assert_sky_metadata(self, request_options_headers(query_api.execute_query))
@patch("skyflow.vault.controller._vault.validate_query_request")
def test_query_handles_generic_error(self, mock_validate):
request = QueryRequest(query="SELECT * from table_name")
query_api = self.vault_client.get_query_api.return_value
- query_api.query_service_execute_query.side_effect = Exception("Generic Exception")
+ query_api.execute_query.side_effect = Exception("Generic Exception")
with self.assertRaises(Exception):
self.vault.query(request)
- query_api.query_service_execute_query.assert_called_once()
+ query_api.execute_query.assert_called_once()
@patch("skyflow.vault.controller._vault.validate_detokenize_request")
@patch("skyflow.vault.controller._vault.parse_detokenize_response")
@@ -605,8 +604,8 @@ def test_detokenize_successful(self, mock_parse_response, mock_validate):
)
expected_tokens_list = [
- V1DetokenizeRecordRequest(token="token1", redaction="PLAIN_TEXT"),
- V1DetokenizeRecordRequest(token="token2", redaction="PLAIN_TEXT")
+ DetokenizeRecordRequest(token="token1", redaction="PLAIN_TEXT"),
+ DetokenizeRecordRequest(token="token2", redaction="PLAIN_TEXT")
]
# Mock API response
@@ -628,7 +627,7 @@ def test_detokenize_successful(self, mock_parse_response, mock_validate):
# Set the return value for parse_detokenize_response
mock_parse_response.return_value = expected_response
tokens_api = self.vault_client.get_tokens_api.return_value
- tokens_api.with_raw_response.record_service_detokenize.return_value = mock_api_response
+ tokens_api.with_raw_response.detokenize.return_value = mock_api_response
# Call the detokenize function
result = self.vault.detokenize(request)
@@ -640,7 +639,7 @@ def test_detokenize_successful(self, mock_parse_response, mock_validate):
# Assert every token and its redaction reach the API
assert_request(
self,
- tokens_api.with_raw_response.record_service_detokenize,
+ tokens_api.with_raw_response.detokenize,
{
"detokenization_parameters": expected_tokens_list,
"continue_on_error": False
@@ -668,12 +667,12 @@ def test_detokenize_handles_generic_error(self, mock_validate):
continue_on_error=False
)
tokens_api = self.vault_client.get_tokens_api.return_value
- tokens_api.record_service_detokenize.side_effect = Exception("Generic Error")
+ tokens_api.detokenize.side_effect = Exception("Generic Error")
with self.assertRaises(Exception):
self.vault.detokenize(request)
- tokens_api.with_raw_response.record_service_detokenize.assert_called_once()
+ tokens_api.with_raw_response.detokenize.assert_called_once()
@patch("skyflow.vault.controller._vault.validate_tokenize_request")
@patch("skyflow.vault.controller._vault.parse_tokenize_response")
@@ -689,8 +688,8 @@ def test_tokenize_successful(self, mock_parse_response, mock_validate):
)
expected_records_list = [
- V1TokenizeRecordRequest(value="value1", column_group="group1"),
- V1TokenizeRecordRequest(value="value2", column_group="group2")
+ TokenizeRecordRequest(value="value1", column_group="group1"),
+ TokenizeRecordRequest(value="value2", column_group="group2")
]
# Mock API response
@@ -710,7 +709,7 @@ def test_tokenize_successful(self, mock_parse_response, mock_validate):
# Set the return value for parse_tokenize_response
mock_parse_response.return_value = expected_response
tokens_api = self.vault_client.get_tokens_api.return_value
- tokens_api.record_service_tokenize.return_value = mock_api_response
+ tokens_api.tokenize.return_value = mock_api_response
# Call the tokenize function
result = self.vault.tokenize(request)
@@ -722,7 +721,7 @@ def test_tokenize_successful(self, mock_parse_response, mock_validate):
# Assert every value and its column group reach the API
assert_request(
self,
- tokens_api.record_service_tokenize,
+ tokens_api.tokenize,
{"tokenization_parameters": expected_records_list},
expected_args=(VAULT_ID,)
)
@@ -739,12 +738,12 @@ def test_tokenize_handles_generic_error(self, mock_validate):
]
)
tokens_api = self.vault_client.get_tokens_api.return_value
- tokens_api.record_service_tokenize.side_effect = Exception("Generic Error")
+ tokens_api.tokenize.side_effect = Exception("Generic Error")
with self.assertRaises(Exception):
self.vault.tokenize(request)
- tokens_api.record_service_tokenize.assert_called_once()
+ tokens_api.tokenize.assert_called_once()
@patch("skyflow.vault.controller._vault.validate_file_upload_request")
def test_upload_file_with_file_path_successful(self, mock_validate):
@@ -764,8 +763,8 @@ def test_upload_file_with_file_path_successful(self, mock_validate):
mock_api_response = Mock()
mock_api_response.data = Mock(skyflow_id="123")
- records_api = self.vault_client.get_records_api.return_value
- records_api.with_raw_response.upload_file_v_2.return_value = mock_api_response
+ records_api = self.vault_client.get_files_api.return_value
+ records_api.with_raw_response.upload_file_v2.return_value = mock_api_response
with patch('builtins.open', mocked_open):
result = self.vault.upload_file(request)
@@ -774,7 +773,7 @@ def test_upload_file_with_file_path_successful(self, mock_validate):
# The file name is derived from the path and the bytes are read off disk
assert_request(
self,
- records_api.with_raw_response.upload_file_v_2,
+ records_api.with_raw_response.upload_file_v2,
{
"table_name": "test_table",
"column_name": "file_column",
@@ -803,8 +802,8 @@ def test_upload_file_with_base64_successful(self, mock_validate):
mock_api_response = Mock()
mock_api_response.data = Mock(skyflow_id="123")
- records_api = self.vault_client.get_records_api.return_value
- records_api.with_raw_response.upload_file_v_2.return_value = mock_api_response
+ records_api = self.vault_client.get_files_api.return_value
+ records_api.with_raw_response.upload_file_v2.return_value = mock_api_response
# Call upload_file
result = self.vault.upload_file(request)
@@ -812,7 +811,7 @@ def test_upload_file_with_base64_successful(self, mock_validate):
# base64 is decoded to bytes and the caller-supplied file name is used
assert_request(
self,
- records_api.with_raw_response.upload_file_v_2,
+ records_api.with_raw_response.upload_file_v2,
{
"table_name": "test_table",
"column_name": "file_column",
@@ -844,8 +843,8 @@ def test_upload_file_with_file_object_successful(self, mock_validate):
mock_api_response = Mock()
mock_api_response.data = Mock(skyflow_id="123")
- records_api = self.vault_client.get_records_api.return_value
- records_api.with_raw_response.upload_file_v_2.return_value = mock_api_response
+ records_api = self.vault_client.get_files_api.return_value
+ records_api.with_raw_response.upload_file_v2.return_value = mock_api_response
# Call upload_file
result = self.vault.upload_file(request)
@@ -853,7 +852,7 @@ def test_upload_file_with_file_object_successful(self, mock_validate):
# The file object is forwarded as-is, named from its own .name attribute
assert_request(
self,
- records_api.with_raw_response.upload_file_v_2,
+ records_api.with_raw_response.upload_file_v2,
{
"table_name": "test_table",
"column_name": "file_column",
@@ -878,8 +877,8 @@ def test_upload_file_handles_api_error(self, mock_validate):
)
# Mock API error
- records_api = self.vault_client.get_records_api.return_value
- records_api.with_raw_response.upload_file_v_2.side_effect = Exception("Upload failed")
+ records_api = self.vault_client.get_files_api.return_value
+ records_api.with_raw_response.upload_file_v2.side_effect = Exception("Upload failed")
# Assert that the exception is propagated
with patch('builtins.open', mock_open(read_data=b"test content")):
@@ -917,8 +916,8 @@ def test_upload_file_without_skyflow_id_successful(self, mock_validate):
mocked_open = mock_open_func(read_data=b"test file content")
mock_api_response = Mock()
mock_api_response.data = Mock(skyflow_id="generated-id-123")
- records_api = self.vault_client.get_records_api.return_value
- records_api.with_raw_response.upload_file_v_2.return_value = mock_api_response
+ records_api = self.vault_client.get_files_api.return_value
+ records_api.with_raw_response.upload_file_v2.return_value = mock_api_response
with patch('builtins.open', mocked_open):
result = self.vault.upload_file(request)
mock_validate.assert_called_once_with(self.vault_client.get_logger(), request)
@@ -926,7 +925,7 @@ def test_upload_file_without_skyflow_id_successful(self, mock_validate):
# skyflow_id is still sent, explicitly as None, so the vault generates one
assert_request(
self,
- records_api.with_raw_response.upload_file_v_2,
+ records_api.with_raw_response.upload_file_v2,
{
"table_name": "test_table",
"column_name": "file_column",
@@ -949,13 +948,13 @@ def test_upload_file_file_path_with_existing_file_name(self, mock_validate):
file_path="/path/to/file.txt",
file_name="already_set.txt"
)
- mock_api = self.vault_client.get_records_api.return_value.with_raw_response
+ mock_api = self.vault_client.get_files_api.return_value.with_raw_response
mock_response = Mock()
mock_response.data.skyflow_id = "sky123"
- mock_api.upload_file_v_2.return_value = mock_response
+ mock_api.upload_file_v2.return_value = mock_response
self.vault.upload_file(request)
- mock_api.upload_file_v_2.assert_called_once()
+ mock_api.upload_file_v2.assert_called_once()
@patch("skyflow.vault.controller._vault.validate_file_upload_request")
def test_upload_file_file_object_without_name_attr(self, mock_validate):
@@ -966,13 +965,13 @@ def test_upload_file_file_object_without_name_attr(self, mock_validate):
column_name="file_col",
file_object=file_obj
)
- mock_api = self.vault_client.get_records_api.return_value.with_raw_response
+ mock_api = self.vault_client.get_files_api.return_value.with_raw_response
mock_response = Mock()
mock_response.data.skyflow_id = "sky123"
- mock_api.upload_file_v_2.return_value = mock_response
+ mock_api.upload_file_v2.return_value = mock_response
self.vault.upload_file(request)
- mock_api.upload_file_v_2.assert_called_once()
+ mock_api.upload_file_v2.assert_called_once()
@patch("skyflow.vault.controller._vault.validate_file_upload_request")
def test_upload_file_no_file_source_returns_none_file(self, mock_validate):
@@ -981,13 +980,13 @@ def test_upload_file_no_file_source_returns_none_file(self, mock_validate):
table=TABLE_NAME,
column_name="file_col"
)
- mock_api = self.vault_client.get_records_api.return_value.with_raw_response
+ mock_api = self.vault_client.get_files_api.return_value.with_raw_response
mock_response = Mock()
mock_response.data.skyflow_id = "sky123"
- mock_api.upload_file_v_2.return_value = mock_response
+ mock_api.upload_file_v2.return_value = mock_response
self.vault.upload_file(request)
- mock_api.upload_file_v_2.assert_called_once()
+ mock_api.upload_file_v2.assert_called_once()
class TestFileUploadValidation(unittest.TestCase):
def setUp(self):
diff --git a/skyvault/tests/vault/detect/test_models.py b/skyvault/tests/vault/detect/test_models.py
deleted file mode 100644
index bec65297..00000000
--- a/skyvault/tests/vault/detect/test_models.py
+++ /dev/null
@@ -1,177 +0,0 @@
-import unittest
-import io
-from skyflow.vault.detect._deidentify_text_response import DeidentifyTextResponse
-from skyflow.vault.detect._reidentify_text_response import ReidentifyTextResponse
-from skyflow.vault.detect._entity_info import EntityInfo
-from skyflow.vault.detect._file_input import FileInput
-from skyflow.vault.detect._text_index import TextIndex
-from skyflow.vault.detect._date_transformation import DateTransformation
-from skyflow.vault.detect._transformations import Transformations
-from skyflow.vault.detect._file import File
-from skyflow.utils.enums import DetectEntities
-
-
-class TestTextIndex(unittest.TestCase):
- def test_repr(self):
- t = TextIndex(start=0, end=4)
- self.assertIn("TextIndex", repr(t))
- self.assertIn("0", repr(t))
-
- def test_str(self):
- t = TextIndex(start=0, end=4)
- self.assertEqual(str(t), repr(t))
-
- def test_attributes(self):
- t = TextIndex(start=5, end=10)
- self.assertEqual(t.start, 5)
- self.assertEqual(t.end, 10)
-
-
-class TestEntityInfo(unittest.TestCase):
- def setUp(self):
- self.text_index = TextIndex(0, 4)
- self.processed_index = TextIndex(0, 8)
-
- def test_repr(self):
- e = EntityInfo(
- token="TOKEN_1", value="John",
- text_index=self.text_index,
- processed_index=self.processed_index,
- entity="NAME", scores={"confidence": 0.9}
- )
- self.assertIn("EntityInfo", repr(e))
- self.assertIn("John", repr(e))
-
- def test_str(self):
- e = EntityInfo(
- token="TOKEN_1", value="John",
- text_index=self.text_index,
- processed_index=self.processed_index,
- entity="NAME", scores={}
- )
- self.assertEqual(str(e), repr(e))
-
- def test_attributes(self):
- e = EntityInfo(
- token="T", value="v",
- text_index=self.text_index,
- processed_index=self.processed_index,
- entity="EMAIL", scores={"s": 1.0}
- )
- self.assertEqual(e.token, "T")
- self.assertEqual(e.entity, "EMAIL")
-
-
-class TestDeidentifyTextResponse(unittest.TestCase):
- def test_repr(self):
- r = DeidentifyTextResponse(
- processed_text="[TOKEN_1]", entities=[], word_count=1, char_count=9
- )
- self.assertIn("DeidentifyTextResponse", repr(r))
-
- def test_str(self):
- r = DeidentifyTextResponse(
- processed_text="[TOKEN_1]", entities=[], word_count=1, char_count=9
- )
- self.assertEqual(str(r), repr(r))
-
- def test_defaults(self):
- r = DeidentifyTextResponse(
- processed_text="text", entities=[], word_count=1, char_count=4
- )
- self.assertIsNone(r.errors)
-
-
-class TestReidentifyTextResponse(unittest.TestCase):
- def test_repr(self):
- r = ReidentifyTextResponse(processed_text="John lives in NYC")
- self.assertIn("ReidentifyTextResponse", repr(r))
-
- def test_str(self):
- r = ReidentifyTextResponse(processed_text="John")
- self.assertEqual(str(r), repr(r))
-
- def test_defaults(self):
- r = ReidentifyTextResponse(processed_text="text")
- self.assertIsNone(r.errors)
-
-
-class TestFileInput(unittest.TestCase):
- def test_repr_with_file(self):
- bio = io.BytesIO(b"data")
- bio.name = "test.txt"
- fi = FileInput(file=bio)
- self.assertIn("FileInput", repr(fi))
-
- def test_str(self):
- fi = FileInput(file_path="/some/path.pdf")
- self.assertEqual(str(fi), repr(fi))
-
- def test_repr_no_file(self):
- fi = FileInput()
- self.assertIn("FileInput", repr(fi))
- self.assertIsNone(fi.file)
- self.assertIsNone(fi.file_path)
-
-
-class TestDateTransformation(unittest.TestCase):
- def test_instantiation(self):
- dt = DateTransformation(
- max_days=30, min_days=1,
- entities=[DetectEntities.DATE]
- )
- self.assertEqual(dt.max, 30)
- self.assertEqual(dt.min, 1)
- self.assertEqual(dt.entities, [DetectEntities.DATE])
-
-
-class TestTransformations(unittest.TestCase):
- def test_instantiation(self):
- dt = DateTransformation(max_days=30, min_days=1, entities=[DetectEntities.DATE])
- t = Transformations(shift_dates=dt)
- self.assertEqual(t.shift_dates, dt)
-
-
-class TestFile(unittest.TestCase):
- def test_properties_with_file(self):
- bio = io.BytesIO(b"hello")
- bio.name = "test.txt"
- f = File(file=bio)
- self.assertEqual(f.name, "test.txt")
- self.assertEqual(f.size, 5)
- self.assertIsNotNone(f.type)
- self.assertIsNotNone(f.last_modified)
-
- def test_properties_without_file(self):
- f = File()
- self.assertIsNone(f.name)
- self.assertIsNone(f.size)
- self.assertIsNone(f.type)
- self.assertIsNone(f.last_modified)
-
- def test_seek_without_file(self):
- f = File()
- result = f.seek(0)
- self.assertIsNone(result)
-
- def test_read_without_file(self):
- f = File()
- result = f.read()
- self.assertIsNone(result)
-
- def test_seek_with_file(self):
- bio = io.BytesIO(b"hello")
- bio.name = "t.txt"
- f = File(file=bio)
- f.seek(0)
- self.assertEqual(f.read(), b"hello")
-
- def test_repr(self):
- bio = io.BytesIO(b"hi")
- bio.name = "t.txt"
- f = File(file=bio)
- self.assertIn("File", repr(f))
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/skyvault/tests/vault/detect/test_reexports.py b/skyvault/tests/vault/detect/test_reexports.py
new file mode 100644
index 00000000..fcaa3561
--- /dev/null
+++ b/skyvault/tests/vault/detect/test_reexports.py
@@ -0,0 +1,52 @@
+import unittest
+
+
+class TestDetectReexports(unittest.TestCase):
+ def test_models_import_from_vault_detect(self):
+ from skyflow.vault.detect import (
+ DeidentifyStringRequest,
+ DeidentifyFileRequest,
+ GetRunRequest,
+ ReidentifyStringRequest,
+ ReidentifyFileRequest,
+ CheckGuardrailsRequest,
+ PollOptions,
+ DetectConfiguration,
+ Detect,
+ Entity,
+ RedactionLevel,
+ )
+
+ request = DeidentifyStringRequest(text="hello", configuration_id="cfg")
+ self.assertEqual(request.text, "hello")
+ self.assertIsNone(PollOptions().wait_time)
+
+ def test_enums_import_from_utils_enums(self):
+ from skyflow.utils.enums import (
+ EntityType,
+ DeidentificationType,
+ ReturnEntitiesType,
+ RedactionType,
+ DeidentifySourceType,
+ ReidentifySourceType,
+ FileDataFormat,
+ DetectRunStatus,
+ ObjectEntityType,
+ ObjectDeidentificationType,
+ OutputTranscriptionType,
+ PdfProcessingMode,
+ MaskingMethod,
+ GuardrailsValidation,
+ )
+
+ self.assertEqual(EntityType.NAME.value, "NAME")
+ self.assertEqual(FileDataFormat.PDF.value, "pdf")
+ self.assertEqual(MaskingMethod.BLUR.value, "BLUR")
+
+ def test_detect_accessor(self):
+ from skyflow import Skyflow
+ self.assertTrue(hasattr(Skyflow, "detect"))
+
+
+if __name__ == "__main__":
+ unittest.main()