diff --git a/.gitignore b/.gitignore index 14e788bb..51b89173 100755 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.env.local **/__pycache__/ **/.speakeasy/temp/ **/.speakeasy/logs/ diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock index 578a0905..6fdbb72d 100755 --- a/.speakeasy/gen.lock +++ b/.speakeasy/gen.lock @@ -1,12 +1,12 @@ lockVersion: 2.0.0 id: 8b5fa338-9106-4734-abf0-e30d67044a90 management: - docChecksum: 8038a5b9e376d44bad2fd4c117922954 - docVersion: 1.1.45 - speakeasyVersion: 1.601.0 - generationVersion: 2.680.0 - releaseVersion: 0.42.3 - configChecksum: 3d02dd7ca437781b3d721fab5d7b9adc + docChecksum: d2d0852108e5c7d29e4de1d909c8b1a0 + docVersion: 1.1.68 + speakeasyVersion: 1.636.2 + generationVersion: 2.723.8 + releaseVersion: 0.43.0 + configChecksum: 3206d0895f6828ba4725a39559160d14 repoURL: https://github.com/Unstructured-IO/unstructured-python-client.git repoSubDirectory: . installationURL: https://github.com/Unstructured-IO/unstructured-python-client.git @@ -16,13 +16,13 @@ features: acceptHeaders: 3.0.0 additionalDependencies: 1.0.0 constsAndDefaults: 1.0.5 - core: 5.19.8 + core: 5.22.1 customCodeRegions: 0.1.1 defaultEnabledRetries: 0.2.0 enumUnions: 0.1.0 envVarSecurityUsage: 0.3.2 examples: 3.0.2 - globalSecurity: 3.0.3 + globalSecurity: 3.0.4 globalSecurityCallbacks: 1.0.0 globalSecurityFlattening: 1.0.0 globalServerURLs: 3.1.1 @@ -34,7 +34,7 @@ features: retries: 3.0.2 sdkHooks: 1.1.0 serverIDs: 3.0.0 - unions: 3.0.4 + unions: 3.1.0 uploadStreams: 1.0.0 generatedFiles: - .gitattributes @@ -101,6 +101,8 @@ generatedFiles: - docs/models/shared/astradbconnectorconfiginput.md - docs/models/shared/azureaisearchconnectorconfig.md - docs/models/shared/azureaisearchconnectorconfiginput.md + - docs/models/shared/azuredestinationconnectorconfig.md + - docs/models/shared/azuredestinationconnectorconfiginput.md - docs/models/shared/azuresourceconnectorconfig.md - docs/models/shared/azuresourceconnectorconfiginput.md - docs/models/shared/bodyrunworkflow.md @@ -229,7 +231,6 @@ generatedFiles: - docs/sdks/general/README.md - docs/sdks/jobs/README.md - docs/sdks/sources/README.md - - docs/sdks/unstructuredclient/README.md - docs/sdks/workflows/README.md - poetry.toml - py.typed @@ -287,6 +288,8 @@ generatedFiles: - src/unstructured_client/models/shared/astradbconnectorconfiginput.py - src/unstructured_client/models/shared/azureaisearchconnectorconfig.py - src/unstructured_client/models/shared/azureaisearchconnectorconfiginput.py + - src/unstructured_client/models/shared/azuredestinationconnectorconfig.py + - src/unstructured_client/models/shared/azuredestinationconnectorconfiginput.py - src/unstructured_client/models/shared/azuresourceconnectorconfig.py - src/unstructured_client/models/shared/azuresourceconnectorconfiginput.py - src/unstructured_client/models/shared/body_run_workflow.py @@ -712,3 +715,4 @@ examples: application/json: {"detail": []} examplesVersion: 1.0.2 generatedTests: {} +releaseNotes: "## Python SDK Changes Detected:\n* `unstructured_client.destinations.create_destination()`: \n * `request.create_destination_connector.config.[azure_destination_connector_config_input]` **Added**\n * `response.config.[azure_destination_connector_config]` **Added**\n* `unstructured_client.destinations.get_destination()`: `response.config.[azure_destination_connector_config]` **Added**\n* `unstructured_client.destinations.list_destinations()`: \n * `request.destination_type` **Changed**\n * `response.[].config.[azure_destination_connector_config]` **Added**\n* `unstructured_client.destinations.update_destination()`: \n * `request.update_destination_connector.config.[azure_destination_connector_config_input]` **Added**\n * `response.config.[azure_destination_connector_config]` **Added**\n" diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock index ca7f6466..ced29a7a 100644 --- a/.speakeasy/workflow.lock +++ b/.speakeasy/workflow.lock @@ -1,21 +1,21 @@ -speakeasyVersion: 1.601.0 +speakeasyVersion: 1.636.2 sources: my-source: sourceNamespace: my-source - sourceRevisionDigest: sha256:8165f715321cd34bcebb6c9bb0734a1791777229937787b8e13707d519b05a5e - sourceBlobDigest: sha256:b4f8d9a6b0f4245c50b5e53298343df470978417248fa3988aeeb84ec9200c93 + sourceRevisionDigest: sha256:01b07e09a6d707c217eea8611647c0d22d909d8e94115821cf0595f81f761d73 + sourceBlobDigest: sha256:a48895f01783a1620d65552d007ff46e4dc2652b37c64dfd8aab3163317e801b tags: - latest - - speakeasy-sdk-regen-1754698272 - - 1.1.45 + - speakeasy-sdk-regen-1756339855 + - 1.1.68 targets: unstructured-python: source: my-source sourceNamespace: my-source - sourceRevisionDigest: sha256:8165f715321cd34bcebb6c9bb0734a1791777229937787b8e13707d519b05a5e - sourceBlobDigest: sha256:b4f8d9a6b0f4245c50b5e53298343df470978417248fa3988aeeb84ec9200c93 + sourceRevisionDigest: sha256:01b07e09a6d707c217eea8611647c0d22d909d8e94115821cf0595f81f761d73 + sourceBlobDigest: sha256:a48895f01783a1620d65552d007ff46e4dc2652b37c64dfd8aab3163317e801b codeSamplesNamespace: my-source-code-samples - codeSamplesRevisionDigest: sha256:a5e11972bfb15e43b7fcb2647b3a7b3e129e9303294f9110670280971b10780a + codeSamplesRevisionDigest: sha256:54f08520c48e4b706c8ffa67fd8c59940bad24add35b7159dea7f73042ff0e44 workflow: workflowVersion: 1.0.0 speakeasyVersion: latest diff --git a/README.md b/README.md index da29a17a..d3459382 100644 --- a/README.md +++ b/README.md @@ -346,6 +346,7 @@ with UnstructuredClient() as uc_client:
The same SDK client can also be used to make asynchronous requests by importing asyncio. + ```python # Asynchronous Example import asyncio diff --git a/RELEASES.md b/RELEASES.md index 562395d9..bd030d56 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1119,4 +1119,14 @@ Based on: ### Generated - [python v0.42.3] . ### Releases -- [PyPI v0.42.3] https://pypi.org/project/unstructured-client/0.42.3 - . \ No newline at end of file +- [PyPI v0.42.3] https://pypi.org/project/unstructured-client/0.42.3 - . + +## 2025-10-09 00:09:58 +### Changes +Based on: +- OpenAPI Doc +- Speakeasy CLI 1.636.2 (2.723.8) https://github.com/speakeasy-api/speakeasy +### Generated +- [python v0.43.0] . +### Releases +- [PyPI v0.43.0] https://pypi.org/project/unstructured-client/0.43.0 - . \ No newline at end of file diff --git a/USAGE.md b/USAGE.md index 43ed3688..19965d4a 100644 --- a/USAGE.md +++ b/USAGE.md @@ -19,6 +19,7 @@ with UnstructuredClient() as uc_client:
The same SDK client can also be used to make asynchronous requests by importing asyncio. + ```python # Asynchronous Example import asyncio diff --git a/codeSamples.yaml b/codeSamples.yaml index f5eda8f2..b28551de 100644 --- a/codeSamples.yaml +++ b/codeSamples.yaml @@ -14,7 +14,7 @@ actions: "x-codeSamples": - "lang": "python" "label": "create_destination" - "source": "from unstructured_client import UnstructuredClient\nfrom unstructured_client.models import shared\n\n\nwith UnstructuredClient() as uc_client:\n\n res = uc_client.destinations.create_destination(request={\n \"create_destination_connector\": {\n \"name\": \"\",\n \"type\": shared.DestinationConnectorType.MOTHERDUCK,\n \"config\": {\n \"index_name\": \"\",\n \"api_key\": \"\",\n \"namespace\": \"\",\n \"batch_size\": 50,\n },\n },\n })\n\n assert res.destination_connector_information is not None\n\n # Handle response\n print(res.destination_connector_information)" + "source": "from unstructured_client import UnstructuredClient\nfrom unstructured_client.models import shared\n\n\nwith UnstructuredClient() as uc_client:\n\n res = uc_client.destinations.create_destination(request={\n \"create_destination_connector\": {\n \"name\": \"\",\n \"type\": shared.DestinationConnectorType.MONGODB,\n \"config\": {\n \"index_name\": \"\",\n \"api_key\": \"\",\n \"namespace\": \"\",\n \"batch_size\": 50,\n },\n },\n })\n\n assert res.destination_connector_information is not None\n\n # Handle response\n print(res.destination_connector_information)" - target: $["paths"]["/api/v1/destinations/{destination_id}"]["delete"] update: "x-codeSamples": @@ -32,7 +32,7 @@ actions: "x-codeSamples": - "lang": "python" "label": "update_destination" - "source": "from unstructured_client import UnstructuredClient\n\n\nwith UnstructuredClient() as uc_client:\n\n res = uc_client.destinations.update_destination(request={\n \"destination_id\": \"9726962d-9d1e-4f84-8787-c7313d183927\",\n \"update_destination_connector\": {\n \"config\": {\n \"bootstrap_servers\": \"\",\n \"port\": 9092,\n \"topic\": \"\",\n \"kafka_api_key\": \"\",\n \"secret\": \"\",\n \"batch_size\": 100,\n },\n },\n })\n\n assert res.destination_connector_information is not None\n\n # Handle response\n print(res.destination_connector_information)" + "source": "from unstructured_client import UnstructuredClient\n\n\nwith UnstructuredClient() as uc_client:\n\n res = uc_client.destinations.update_destination(request={\n \"destination_id\": \"962d9d1e-f847-487c-a731-3d18392716fb\",\n \"update_destination_connector\": {\n \"config\": {\n \"remote_url\": \"https://lined-clamp.info\",\n \"service_account_key\": \"\",\n },\n },\n })\n\n assert res.destination_connector_information is not None\n\n # Handle response\n print(res.destination_connector_information)" - target: $["paths"]["/api/v1/destinations/{destination_id}/connection-check"]["get"] update: "x-codeSamples": diff --git a/docs/models/shared/config.md b/docs/models/shared/config.md index 03abce7e..b6441eb9 100644 --- a/docs/models/shared/config.md +++ b/docs/models/shared/config.md @@ -3,6 +3,12 @@ ## Supported Types +### `shared.AzureDestinationConnectorConfigInput` + +```python +value: shared.AzureDestinationConnectorConfigInput = /* values here */ +``` + ### `shared.AstraDBConnectorConfigInput` ```python diff --git a/docs/models/shared/destinationconnectorinformationconfig.md b/docs/models/shared/destinationconnectorinformationconfig.md index f7871f5a..70b163e8 100644 --- a/docs/models/shared/destinationconnectorinformationconfig.md +++ b/docs/models/shared/destinationconnectorinformationconfig.md @@ -3,6 +3,12 @@ ## Supported Types +### `shared.AzureDestinationConnectorConfig` + +```python +value: shared.AzureDestinationConnectorConfig = /* values here */ +``` + ### `shared.AstraDBConnectorConfig` ```python diff --git a/docs/models/shared/destinationconnectortype.md b/docs/models/shared/destinationconnectortype.md index d0b8f5ab..02159f7f 100644 --- a/docs/models/shared/destinationconnectortype.md +++ b/docs/models/shared/destinationconnectortype.md @@ -5,6 +5,7 @@ | Name | Value | | -------------------------------- | -------------------------------- | +| `AZURE` | azure | | `ASTRADB` | astradb | | `AZURE_AI_SEARCH` | azure_ai_search | | `COUCHBASE` | couchbase | diff --git a/docs/models/shared/updatedestinationconnectorconfig.md b/docs/models/shared/updatedestinationconnectorconfig.md index a0424473..ea3688cb 100644 --- a/docs/models/shared/updatedestinationconnectorconfig.md +++ b/docs/models/shared/updatedestinationconnectorconfig.md @@ -3,6 +3,12 @@ ## Supported Types +### `shared.AzureDestinationConnectorConfigInput` + +```python +value: shared.AzureDestinationConnectorConfigInput = /* values here */ +``` + ### `shared.AstraDBConnectorConfigInput` ```python diff --git a/docs/sdks/unstructuredclient/README.md b/docs/sdks/unstructuredclient/README.md deleted file mode 100644 index 895459f0..00000000 --- a/docs/sdks/unstructuredclient/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# UnstructuredClient SDK - -## Overview - -### Available Operations diff --git a/gen.yaml b/gen.yaml index 1060b902..106f8f13 100644 --- a/gen.yaml +++ b/gen.yaml @@ -13,12 +13,13 @@ generation: auth: oAuth2ClientCredentialsEnabled: false oAuth2PasswordEnabled: false + hoistGlobalSecurity: true tests: generateTests: true generateNewTests: false skipResponseBodyAssertions: false python: - version: 0.42.3 + version: 0.43.0 additionalDependencies: dev: deepdiff: '>=6.0' @@ -36,6 +37,10 @@ python: httpx: '>=0.27.0' pypdf: '>=4.0' requests-toolbelt: '>=1.0.0' + allowedRedefinedBuiltins: + - id + - object + asyncMode: both authors: - Unstructured baseErrorName: UnstructuredClientError @@ -58,6 +63,7 @@ python: shared: models/shared webhooks: models/webhooks inputModelSuffix: input + legacyPyright: true license: MIT maxMethodParams: 0 methodArguments: require-security-and-request @@ -69,4 +75,5 @@ python: pytestFilterWarnings: [] pytestTimeout: 0 responseFormat: envelope + sseFlatResponse: false templateVersion: v2 diff --git a/pyproject.toml b/pyproject.toml index 8684a295..fa6b7d8f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "unstructured-client" -version = "0.42.3" +version = "0.43.0" description = "Python Client SDK for Unstructured API" authors = [{ name = "Unstructured" },] readme = "README-PYPI.md" diff --git a/scripts/prepare_readme.py b/scripts/prepare_readme.py index 52e872a1..d75b47bc 100644 --- a/scripts/prepare_readme.py +++ b/scripts/prepare_readme.py @@ -10,12 +10,17 @@ GITHUB_URL = ( GITHUB_URL[: -len(".git")] if GITHUB_URL.endswith(".git") else GITHUB_URL ) + REPO_SUBDIR = "." + # Ensure the subdirectory has a trailing slash + if not REPO_SUBDIR.endswith("/"): + REPO_SUBDIR += "/" # links on PyPI should have absolute URLs readme_contents = re.sub( r"(\[[^\]]+\]\()((?!https?:)[^\)]+)(\))", lambda m: m.group(1) + GITHUB_URL + "/blob/master/" + + REPO_SUBDIR + m.group(2) + m.group(3), readme_contents, diff --git a/src/unstructured_client/_version.py b/src/unstructured_client/_version.py index a5be6a7b..370feda8 100644 --- a/src/unstructured_client/_version.py +++ b/src/unstructured_client/_version.py @@ -3,10 +3,10 @@ import importlib.metadata __title__: str = "unstructured-client" -__version__: str = "0.42.3" -__openapi_doc_version__: str = "1.1.45" -__gen_version__: str = "2.680.0" -__user_agent__: str = "speakeasy-sdk/python 0.42.3 2.680.0 1.1.45 unstructured-client" +__version__: str = "0.43.0" +__openapi_doc_version__: str = "1.1.68" +__gen_version__: str = "2.723.8" +__user_agent__: str = "speakeasy-sdk/python 0.43.0 2.723.8 1.1.68 unstructured-client" try: if __package__ is not None: diff --git a/src/unstructured_client/basesdk.py b/src/unstructured_client/basesdk.py index a1c0f684..d429490c 100644 --- a/src/unstructured_client/basesdk.py +++ b/src/unstructured_client/basesdk.py @@ -20,9 +20,19 @@ class BaseSDK: sdk_configuration: SDKConfiguration + parent_ref: Optional[object] = None + """ + Reference to the root SDK instance, if any. This will prevent it from + being garbage collected while there are active streams. + """ - def __init__(self, sdk_config: SDKConfiguration) -> None: + def __init__( + self, + sdk_config: SDKConfiguration, + parent_ref: Optional[object] = None, + ) -> None: self.sdk_configuration = sdk_config + self.parent_ref = parent_ref def _get_url(self, base_url, url_variables): sdk_url, sdk_variables = self.sdk_configuration.get_server_details() diff --git a/src/unstructured_client/destinations.py b/src/unstructured_client/destinations.py index 9ad0a291..1947c992 100644 --- a/src/unstructured_client/destinations.py +++ b/src/unstructured_client/destinations.py @@ -81,7 +81,7 @@ def create_connection_check_destinations( config=self.sdk_configuration, base_url=base_url or "", operation_id="create_connection_check_destinations", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -184,7 +184,7 @@ async def create_connection_check_destinations_async( config=self.sdk_configuration, base_url=base_url or "", operation_id="create_connection_check_destinations", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -292,7 +292,7 @@ def create_destination( config=self.sdk_configuration, base_url=base_url or "", operation_id="create_destination", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -400,7 +400,7 @@ async def create_destination_async( config=self.sdk_configuration, base_url=base_url or "", operation_id="create_destination", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -501,7 +501,7 @@ def delete_destination( config=self.sdk_configuration, base_url=base_url or "", operation_id="delete_destination", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -600,7 +600,7 @@ async def delete_destination_async( config=self.sdk_configuration, base_url=base_url or "", operation_id="delete_destination", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -701,7 +701,7 @@ def get_connection_check_destinations( config=self.sdk_configuration, base_url=base_url or "", operation_id="get_connection_check_destinations", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -804,7 +804,7 @@ async def get_connection_check_destinations_async( config=self.sdk_configuration, base_url=base_url or "", operation_id="get_connection_check_destinations", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -904,7 +904,7 @@ def get_destination( config=self.sdk_configuration, base_url=base_url or "", operation_id="get_destination", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -1004,7 +1004,7 @@ async def get_destination_async( config=self.sdk_configuration, base_url=base_url or "", operation_id="get_destination", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -1105,7 +1105,7 @@ def list_destinations( config=self.sdk_configuration, base_url=base_url or "", operation_id="list_destinations", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -1206,7 +1206,7 @@ async def list_destinations_async( config=self.sdk_configuration, base_url=base_url or "", operation_id="list_destinations", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -1314,7 +1314,7 @@ def update_destination( config=self.sdk_configuration, base_url=base_url or "", operation_id="update_destination", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -1422,7 +1422,7 @@ async def update_destination_async( config=self.sdk_configuration, base_url=base_url or "", operation_id="update_destination", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, diff --git a/src/unstructured_client/httpclient.py b/src/unstructured_client/httpclient.py index 47b052cb..89560b56 100644 --- a/src/unstructured_client/httpclient.py +++ b/src/unstructured_client/httpclient.py @@ -107,7 +107,6 @@ def close_clients( # to them from the owning SDK instance and they can be reaped. owner.client = None owner.async_client = None - if sync_client is not None and not sync_client_supplied: try: sync_client.close() diff --git a/src/unstructured_client/jobs.py b/src/unstructured_client/jobs.py index ba620032..3c165ff8 100644 --- a/src/unstructured_client/jobs.py +++ b/src/unstructured_client/jobs.py @@ -78,7 +78,7 @@ def cancel_job( config=self.sdk_configuration, base_url=base_url or "", operation_id="cancel_job", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -176,7 +176,7 @@ async def cancel_job_async( config=self.sdk_configuration, base_url=base_url or "", operation_id="cancel_job", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -275,7 +275,7 @@ def download_job_output( config=self.sdk_configuration, base_url=base_url or "", operation_id="download_job_output", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -374,7 +374,7 @@ async def download_job_output_async( config=self.sdk_configuration, base_url=base_url or "", operation_id="download_job_output", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -470,7 +470,7 @@ def get_job( config=self.sdk_configuration, base_url=base_url or "", operation_id="get_job", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -568,7 +568,7 @@ async def get_job_async( config=self.sdk_configuration, base_url=base_url or "", operation_id="get_job", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -668,7 +668,7 @@ def get_job_details( config=self.sdk_configuration, base_url=base_url or "", operation_id="get_job_details", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -768,7 +768,7 @@ async def get_job_details_async( config=self.sdk_configuration, base_url=base_url or "", operation_id="get_job_details", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -869,7 +869,7 @@ def get_job_failed_files( config=self.sdk_configuration, base_url=base_url or "", operation_id="get_job_failed_files", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -970,7 +970,7 @@ async def get_job_failed_files_async( config=self.sdk_configuration, base_url=base_url or "", operation_id="get_job_failed_files", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -1068,7 +1068,7 @@ def list_jobs( config=self.sdk_configuration, base_url=base_url or "", operation_id="list_jobs", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -1166,7 +1166,7 @@ async def list_jobs_async( config=self.sdk_configuration, base_url=base_url or "", operation_id="list_jobs", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, diff --git a/src/unstructured_client/models/errors/__init__.py b/src/unstructured_client/models/errors/__init__.py index 1aa6130f..c7c3b5d1 100644 --- a/src/unstructured_client/models/errors/__init__.py +++ b/src/unstructured_client/models/errors/__init__.py @@ -1,8 +1,10 @@ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" +from .unstructuredclienterror import UnstructuredClientError from typing import TYPE_CHECKING from importlib import import_module import builtins +import sys if TYPE_CHECKING: from .httpvalidationerror import ( @@ -14,7 +16,6 @@ from .responsevalidationerror import ResponseValidationError from .sdkerror import SDKError from .servererror import ServerError, ServerErrorData - from .unstructuredclienterror import UnstructuredClientError __all__ = [ "Detail", @@ -37,10 +38,21 @@ "SDKError": ".sdkerror", "ServerError": ".servererror", "ServerErrorData": ".servererror", - "UnstructuredClientError": ".unstructuredclienterror", } +def dynamic_import(modname, retries=3): + for attempt in range(retries): + try: + return import_module(modname, __package__) + except KeyError: + # Clear any half-initialized module and retry + sys.modules.pop(modname, None) + if attempt == retries - 1: + break + raise KeyError(f"Failed to import module '{modname}' after {retries} attempts") + + def __getattr__(attr_name: str) -> object: module_name = _dynamic_imports.get(attr_name) if module_name is None: @@ -49,7 +61,7 @@ def __getattr__(attr_name: str) -> object: ) try: - module = import_module(module_name, __package__) + module = dynamic_import(module_name) result = getattr(module, attr_name) return result except ImportError as e: diff --git a/src/unstructured_client/models/errors/httpvalidationerror.py b/src/unstructured_client/models/errors/httpvalidationerror.py index 4be2ca24..97f9e47d 100644 --- a/src/unstructured_client/models/errors/httpvalidationerror.py +++ b/src/unstructured_client/models/errors/httpvalidationerror.py @@ -1,6 +1,7 @@ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" from __future__ import annotations +from dataclasses import dataclass, field import httpx from typing import List, Optional, Union from typing_extensions import TypeAliasType @@ -23,8 +24,9 @@ class HTTPValidationErrorData(BaseModel): detail: Optional[Detail] = None +@dataclass(frozen=True) class HTTPValidationError(UnstructuredClientError): - data: HTTPValidationErrorData + data: HTTPValidationErrorData = field(hash=False) def __init__( self, @@ -34,4 +36,4 @@ def __init__( ): message = body or raw_response.text super().__init__(message, raw_response, body) - self.data = data + object.__setattr__(self, "data", data) diff --git a/src/unstructured_client/models/errors/no_response_error.py b/src/unstructured_client/models/errors/no_response_error.py index f98beea2..b710ea2b 100644 --- a/src/unstructured_client/models/errors/no_response_error.py +++ b/src/unstructured_client/models/errors/no_response_error.py @@ -1,12 +1,16 @@ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" +from dataclasses import dataclass + + +@dataclass(frozen=True) class NoResponseError(Exception): """Error raised when no HTTP response is received from the server.""" message: str def __init__(self, message: str = "No response received"): - self.message = message + object.__setattr__(self, "message", message) super().__init__(message) def __str__(self): diff --git a/src/unstructured_client/models/errors/responsevalidationerror.py b/src/unstructured_client/models/errors/responsevalidationerror.py index c3c09737..99634229 100644 --- a/src/unstructured_client/models/errors/responsevalidationerror.py +++ b/src/unstructured_client/models/errors/responsevalidationerror.py @@ -2,10 +2,12 @@ import httpx from typing import Optional +from dataclasses import dataclass from unstructured_client.models.errors import UnstructuredClientError +@dataclass(frozen=True) class ResponseValidationError(UnstructuredClientError): """Error raised when there is a type mismatch between the response data and the expected Pydantic model.""" diff --git a/src/unstructured_client/models/errors/sdkerror.py b/src/unstructured_client/models/errors/sdkerror.py index 51e10405..52dc82cd 100644 --- a/src/unstructured_client/models/errors/sdkerror.py +++ b/src/unstructured_client/models/errors/sdkerror.py @@ -2,12 +2,14 @@ import httpx from typing import Optional +from dataclasses import dataclass from unstructured_client.models.errors import UnstructuredClientError MAX_MESSAGE_LEN = 10_000 +@dataclass(frozen=True) class SDKError(UnstructuredClientError): """The fallback error class if no more specific error class is matched.""" diff --git a/src/unstructured_client/models/errors/servererror.py b/src/unstructured_client/models/errors/servererror.py index 2b4c81a5..6b9412f5 100644 --- a/src/unstructured_client/models/errors/servererror.py +++ b/src/unstructured_client/models/errors/servererror.py @@ -1,6 +1,7 @@ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" from __future__ import annotations +from dataclasses import dataclass, field import httpx from typing import Optional from unstructured_client.models.errors import UnstructuredClientError @@ -11,8 +12,9 @@ class ServerErrorData(BaseModel): detail: Optional[str] = None +@dataclass(frozen=True) class ServerError(UnstructuredClientError): - data: ServerErrorData + data: ServerErrorData = field(hash=False) def __init__( self, @@ -22,4 +24,4 @@ def __init__( ): message = body or raw_response.text super().__init__(message, raw_response, body) - self.data = data + object.__setattr__(self, "data", data) diff --git a/src/unstructured_client/models/errors/unstructuredclienterror.py b/src/unstructured_client/models/errors/unstructuredclienterror.py index 054fb875..c37dbb62 100644 --- a/src/unstructured_client/models/errors/unstructuredclienterror.py +++ b/src/unstructured_client/models/errors/unstructuredclienterror.py @@ -2,25 +2,29 @@ import httpx from typing import Optional +from dataclasses import dataclass, field +@dataclass(frozen=True) class UnstructuredClientError(Exception): """The base class for all HTTP error responses.""" message: str status_code: int body: str - headers: httpx.Headers - raw_response: httpx.Response + headers: httpx.Headers = field(hash=False) + raw_response: httpx.Response = field(hash=False) def __init__( self, message: str, raw_response: httpx.Response, body: Optional[str] = None ): - self.message = message - self.status_code = raw_response.status_code - self.body = body if body is not None else raw_response.text - self.headers = raw_response.headers - self.raw_response = raw_response + object.__setattr__(self, "message", message) + object.__setattr__(self, "status_code", raw_response.status_code) + object.__setattr__( + self, "body", body if body is not None else raw_response.text + ) + object.__setattr__(self, "headers", raw_response.headers) + object.__setattr__(self, "raw_response", raw_response) def __str__(self): return self.message diff --git a/src/unstructured_client/models/operations/__init__.py b/src/unstructured_client/models/operations/__init__.py index 8c6fbfc2..1818438c 100644 --- a/src/unstructured_client/models/operations/__init__.py +++ b/src/unstructured_client/models/operations/__init__.py @@ -3,6 +3,7 @@ from typing import TYPE_CHECKING from importlib import import_module import builtins +import sys if TYPE_CHECKING: from .cancel_job import ( @@ -391,6 +392,18 @@ } +def dynamic_import(modname, retries=3): + for attempt in range(retries): + try: + return import_module(modname, __package__) + except KeyError: + # Clear any half-initialized module and retry + sys.modules.pop(modname, None) + if attempt == retries - 1: + break + raise KeyError(f"Failed to import module '{modname}' after {retries} attempts") + + def __getattr__(attr_name: str) -> object: module_name = _dynamic_imports.get(attr_name) if module_name is None: @@ -399,7 +412,7 @@ def __getattr__(attr_name: str) -> object: ) try: - module = import_module(module_name, __package__) + module = dynamic_import(module_name) result = getattr(module, attr_name) return result except ImportError as e: diff --git a/src/unstructured_client/models/shared/__init__.py b/src/unstructured_client/models/shared/__init__.py index 0ab9d4af..66073d1b 100644 --- a/src/unstructured_client/models/shared/__init__.py +++ b/src/unstructured_client/models/shared/__init__.py @@ -3,6 +3,7 @@ from typing import TYPE_CHECKING from importlib import import_module import builtins +import sys if TYPE_CHECKING: from .astradbconnectorconfig import ( @@ -21,6 +22,14 @@ AzureAISearchConnectorConfigInput, AzureAISearchConnectorConfigInputTypedDict, ) + from .azuredestinationconnectorconfig import ( + AzureDestinationConnectorConfig, + AzureDestinationConnectorConfigTypedDict, + ) + from .azuredestinationconnectorconfiginput import ( + AzureDestinationConnectorConfigInput, + AzureDestinationConnectorConfigInputTypedDict, + ) from .azuresourceconnectorconfig import ( AzureSourceConnectorConfig, AzureSourceConnectorConfigTypedDict, @@ -413,6 +422,10 @@ "AzureAISearchConnectorConfigInput", "AzureAISearchConnectorConfigInputTypedDict", "AzureAISearchConnectorConfigTypedDict", + "AzureDestinationConnectorConfig", + "AzureDestinationConnectorConfigInput", + "AzureDestinationConnectorConfigInputTypedDict", + "AzureDestinationConnectorConfigTypedDict", "AzureSourceConnectorConfig", "AzureSourceConnectorConfigInput", "AzureSourceConnectorConfigInputTypedDict", @@ -654,6 +667,10 @@ "AzureAISearchConnectorConfigTypedDict": ".azureaisearchconnectorconfig", "AzureAISearchConnectorConfigInput": ".azureaisearchconnectorconfiginput", "AzureAISearchConnectorConfigInputTypedDict": ".azureaisearchconnectorconfiginput", + "AzureDestinationConnectorConfig": ".azuredestinationconnectorconfig", + "AzureDestinationConnectorConfigTypedDict": ".azuredestinationconnectorconfig", + "AzureDestinationConnectorConfigInput": ".azuredestinationconnectorconfiginput", + "AzureDestinationConnectorConfigInputTypedDict": ".azuredestinationconnectorconfiginput", "AzureSourceConnectorConfig": ".azuresourceconnectorconfig", "AzureSourceConnectorConfigTypedDict": ".azuresourceconnectorconfig", "AzureSourceConnectorConfigInput": ".azuresourceconnectorconfiginput", @@ -887,6 +904,18 @@ } +def dynamic_import(modname, retries=3): + for attempt in range(retries): + try: + return import_module(modname, __package__) + except KeyError: + # Clear any half-initialized module and retry + sys.modules.pop(modname, None) + if attempt == retries - 1: + break + raise KeyError(f"Failed to import module '{modname}' after {retries} attempts") + + def __getattr__(attr_name: str) -> object: module_name = _dynamic_imports.get(attr_name) if module_name is None: @@ -895,7 +924,7 @@ def __getattr__(attr_name: str) -> object: ) try: - module = import_module(module_name, __package__) + module = dynamic_import(module_name) result = getattr(module, attr_name) return result except ImportError as e: diff --git a/src/unstructured_client/models/shared/createdestinationconnector.py b/src/unstructured_client/models/shared/createdestinationconnector.py index 3275fd05..f6b50154 100644 --- a/src/unstructured_client/models/shared/createdestinationconnector.py +++ b/src/unstructured_client/models/shared/createdestinationconnector.py @@ -9,6 +9,10 @@ AzureAISearchConnectorConfigInput, AzureAISearchConnectorConfigInputTypedDict, ) +from .azuredestinationconnectorconfiginput import ( + AzureDestinationConnectorConfigInput, + AzureDestinationConnectorConfigInputTypedDict, +) from .couchbasedestinationconnectorconfiginput import ( CouchbaseDestinationConnectorConfigInput, CouchbaseDestinationConnectorConfigInputTypedDict, @@ -98,20 +102,21 @@ Union[ GCSDestinationConnectorConfigInputTypedDict, ElasticsearchConnectorConfigInputTypedDict, + MongoDBConnectorConfigInputTypedDict, AzureAISearchConnectorConfigInputTypedDict, WeaviateDestinationConnectorConfigInputTypedDict, - MongoDBConnectorConfigInputTypedDict, DeltaTableConnectorConfigInputTypedDict, QdrantCloudDestinationConnectorConfigInputTypedDict, PineconeDestinationConnectorConfigInputTypedDict, + AzureDestinationConnectorConfigInputTypedDict, Neo4jDestinationConnectorConfigInputTypedDict, OneDriveDestinationConnectorConfigInputTypedDict, S3DestinationConnectorConfigInputTypedDict, AstraDBConnectorConfigInputTypedDict, PostgresDestinationConnectorConfigInputTypedDict, - DatabricksVolumesConnectorConfigInputTypedDict, MilvusDestinationConnectorConfigInputTypedDict, KafkaCloudDestinationConnectorConfigInputTypedDict, + DatabricksVolumesConnectorConfigInputTypedDict, CouchbaseDestinationConnectorConfigInputTypedDict, RedisDestinationConnectorConfigInputTypedDict, DatabricksVDTDestinationConnectorConfigInputTypedDict, @@ -127,20 +132,21 @@ Union[ GCSDestinationConnectorConfigInput, ElasticsearchConnectorConfigInput, + MongoDBConnectorConfigInput, AzureAISearchConnectorConfigInput, WeaviateDestinationConnectorConfigInput, - MongoDBConnectorConfigInput, DeltaTableConnectorConfigInput, QdrantCloudDestinationConnectorConfigInput, PineconeDestinationConnectorConfigInput, + AzureDestinationConnectorConfigInput, Neo4jDestinationConnectorConfigInput, OneDriveDestinationConnectorConfigInput, S3DestinationConnectorConfigInput, AstraDBConnectorConfigInput, PostgresDestinationConnectorConfigInput, - DatabricksVolumesConnectorConfigInput, MilvusDestinationConnectorConfigInput, KafkaCloudDestinationConnectorConfigInput, + DatabricksVolumesConnectorConfigInput, CouchbaseDestinationConnectorConfigInput, RedisDestinationConnectorConfigInput, DatabricksVDTDestinationConnectorConfigInput, diff --git a/src/unstructured_client/models/shared/destinationconnectorinformation.py b/src/unstructured_client/models/shared/destinationconnectorinformation.py index 0e912623..6c988b4e 100644 --- a/src/unstructured_client/models/shared/destinationconnectorinformation.py +++ b/src/unstructured_client/models/shared/destinationconnectorinformation.py @@ -9,6 +9,10 @@ AzureAISearchConnectorConfig, AzureAISearchConnectorConfigTypedDict, ) +from .azuredestinationconnectorconfig import ( + AzureDestinationConnectorConfig, + AzureDestinationConnectorConfigTypedDict, +) from .couchbasedestinationconnectorconfig import ( CouchbaseDestinationConnectorConfig, CouchbaseDestinationConnectorConfigTypedDict, @@ -106,20 +110,21 @@ Union[ GCSDestinationConnectorConfigTypedDict, ElasticsearchConnectorConfigTypedDict, + MongoDBConnectorConfigTypedDict, AzureAISearchConnectorConfigTypedDict, WeaviateDestinationConnectorConfigTypedDict, - MongoDBConnectorConfigTypedDict, DeltaTableConnectorConfigTypedDict, QdrantCloudDestinationConnectorConfigTypedDict, PineconeDestinationConnectorConfigTypedDict, + AzureDestinationConnectorConfigTypedDict, AstraDBConnectorConfigTypedDict, Neo4jDestinationConnectorConfigTypedDict, OneDriveDestinationConnectorConfigTypedDict, S3DestinationConnectorConfigTypedDict, PostgresDestinationConnectorConfigTypedDict, - DatabricksVolumesConnectorConfigTypedDict, MilvusDestinationConnectorConfigTypedDict, KafkaCloudDestinationConnectorConfigTypedDict, + DatabricksVolumesConnectorConfigTypedDict, CouchbaseDestinationConnectorConfigTypedDict, RedisDestinationConnectorConfigTypedDict, DatabricksVDTDestinationConnectorConfigTypedDict, @@ -135,20 +140,21 @@ Union[ GCSDestinationConnectorConfig, ElasticsearchConnectorConfig, + MongoDBConnectorConfig, AzureAISearchConnectorConfig, WeaviateDestinationConnectorConfig, - MongoDBConnectorConfig, DeltaTableConnectorConfig, QdrantCloudDestinationConnectorConfig, PineconeDestinationConnectorConfig, + AzureDestinationConnectorConfig, AstraDBConnectorConfig, Neo4jDestinationConnectorConfig, OneDriveDestinationConnectorConfig, S3DestinationConnectorConfig, PostgresDestinationConnectorConfig, - DatabricksVolumesConnectorConfig, MilvusDestinationConnectorConfig, KafkaCloudDestinationConnectorConfig, + DatabricksVolumesConnectorConfig, CouchbaseDestinationConnectorConfig, RedisDestinationConnectorConfig, DatabricksVDTDestinationConnectorConfig, diff --git a/src/unstructured_client/models/shared/destinationconnectortype.py b/src/unstructured_client/models/shared/destinationconnectortype.py index 6de4b97c..d463db75 100644 --- a/src/unstructured_client/models/shared/destinationconnectortype.py +++ b/src/unstructured_client/models/shared/destinationconnectortype.py @@ -6,6 +6,7 @@ class DestinationConnectorType(str, Enum, metaclass=utils.OpenEnumMeta): + AZURE = "azure" ASTRADB = "astradb" AZURE_AI_SEARCH = "azure_ai_search" COUCHBASE = "couchbase" diff --git a/src/unstructured_client/models/shared/updatedestinationconnector.py b/src/unstructured_client/models/shared/updatedestinationconnector.py index e10814f6..f4a189de 100644 --- a/src/unstructured_client/models/shared/updatedestinationconnector.py +++ b/src/unstructured_client/models/shared/updatedestinationconnector.py @@ -9,6 +9,10 @@ AzureAISearchConnectorConfigInput, AzureAISearchConnectorConfigInputTypedDict, ) +from .azuredestinationconnectorconfiginput import ( + AzureDestinationConnectorConfigInput, + AzureDestinationConnectorConfigInputTypedDict, +) from .couchbasedestinationconnectorconfiginput import ( CouchbaseDestinationConnectorConfigInput, CouchbaseDestinationConnectorConfigInputTypedDict, @@ -95,20 +99,21 @@ Union[ GCSDestinationConnectorConfigInputTypedDict, ElasticsearchConnectorConfigInputTypedDict, + MongoDBConnectorConfigInputTypedDict, AzureAISearchConnectorConfigInputTypedDict, WeaviateDestinationConnectorConfigInputTypedDict, - MongoDBConnectorConfigInputTypedDict, DeltaTableConnectorConfigInputTypedDict, QdrantCloudDestinationConnectorConfigInputTypedDict, PineconeDestinationConnectorConfigInputTypedDict, + AzureDestinationConnectorConfigInputTypedDict, Neo4jDestinationConnectorConfigInputTypedDict, OneDriveDestinationConnectorConfigInputTypedDict, S3DestinationConnectorConfigInputTypedDict, AstraDBConnectorConfigInputTypedDict, PostgresDestinationConnectorConfigInputTypedDict, - DatabricksVolumesConnectorConfigInputTypedDict, MilvusDestinationConnectorConfigInputTypedDict, KafkaCloudDestinationConnectorConfigInputTypedDict, + DatabricksVolumesConnectorConfigInputTypedDict, CouchbaseDestinationConnectorConfigInputTypedDict, RedisDestinationConnectorConfigInputTypedDict, DatabricksVDTDestinationConnectorConfigInputTypedDict, @@ -124,20 +129,21 @@ Union[ GCSDestinationConnectorConfigInput, ElasticsearchConnectorConfigInput, + MongoDBConnectorConfigInput, AzureAISearchConnectorConfigInput, WeaviateDestinationConnectorConfigInput, - MongoDBConnectorConfigInput, DeltaTableConnectorConfigInput, QdrantCloudDestinationConnectorConfigInput, PineconeDestinationConnectorConfigInput, + AzureDestinationConnectorConfigInput, Neo4jDestinationConnectorConfigInput, OneDriveDestinationConnectorConfigInput, S3DestinationConnectorConfigInput, AstraDBConnectorConfigInput, PostgresDestinationConnectorConfigInput, - DatabricksVolumesConnectorConfigInput, MilvusDestinationConnectorConfigInput, KafkaCloudDestinationConnectorConfigInput, + DatabricksVolumesConnectorConfigInput, CouchbaseDestinationConnectorConfigInput, RedisDestinationConnectorConfigInput, DatabricksVDTDestinationConnectorConfigInput, diff --git a/src/unstructured_client/sdk.py b/src/unstructured_client/sdk.py index 014bb146..5d70378b 100644 --- a/src/unstructured_client/sdk.py +++ b/src/unstructured_client/sdk.py @@ -7,6 +7,7 @@ from .utils.retries import RetryConfig import httpx import importlib +import sys from typing import Any, Callable, Dict, Optional, TYPE_CHECKING, Union, cast from unstructured_client import utils from unstructured_client._hooks import SDKHooks @@ -63,7 +64,7 @@ def __init__( """ client_supplied = True if client is None: - client = httpx.Client() + client = httpx.Client(follow_redirects=True) client_supplied = False assert issubclass( @@ -72,7 +73,7 @@ def __init__( async_client_supplied = True if async_client is None: - async_client = httpx.AsyncClient() + async_client = httpx.AsyncClient(follow_redirects=True) async_client_supplied = False if debug_logger is None: @@ -107,6 +108,7 @@ def __init__( timeout_ms=timeout_ms, debug_logger=debug_logger, ), + parent_ref=self, ) hooks = SDKHooks() @@ -131,13 +133,24 @@ def __init__( self.sdk_configuration.async_client_supplied, ) + def dynamic_import(self, modname, retries=3): + for attempt in range(retries): + try: + return importlib.import_module(modname) + except KeyError: + # Clear any half-initialized module and retry + sys.modules.pop(modname, None) + if attempt == retries - 1: + break + raise KeyError(f"Failed to import module '{modname}' after {retries} attempts") + def __getattr__(self, name: str): if name in self._sub_sdk_map: module_path, class_name = self._sub_sdk_map[name] try: - module = importlib.import_module(module_path) + module = self.dynamic_import(module_path) klass = getattr(module, class_name) - instance = klass(self.sdk_configuration) + instance = klass(self.sdk_configuration, parent_ref=self) setattr(self, name, instance) return instance except ImportError as e: diff --git a/src/unstructured_client/sources.py b/src/unstructured_client/sources.py index 48bd82da..21399d4e 100644 --- a/src/unstructured_client/sources.py +++ b/src/unstructured_client/sources.py @@ -81,7 +81,7 @@ def create_connection_check_sources( config=self.sdk_configuration, base_url=base_url or "", operation_id="create_connection_check_sources", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -184,7 +184,7 @@ async def create_connection_check_sources_async( config=self.sdk_configuration, base_url=base_url or "", operation_id="create_connection_check_sources", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -291,7 +291,7 @@ def create_source( config=self.sdk_configuration, base_url=base_url or "", operation_id="create_source", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -398,7 +398,7 @@ async def create_source_async( config=self.sdk_configuration, base_url=base_url or "", operation_id="create_source", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -498,7 +498,7 @@ def delete_source( config=self.sdk_configuration, base_url=base_url or "", operation_id="delete_source", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -596,7 +596,7 @@ async def delete_source_async( config=self.sdk_configuration, base_url=base_url or "", operation_id="delete_source", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -697,7 +697,7 @@ def get_connection_check_sources( config=self.sdk_configuration, base_url=base_url or "", operation_id="get_connection_check_sources", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -800,7 +800,7 @@ async def get_connection_check_sources_async( config=self.sdk_configuration, base_url=base_url or "", operation_id="get_connection_check_sources", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -900,7 +900,7 @@ def get_source( config=self.sdk_configuration, base_url=base_url or "", operation_id="get_source", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -1000,7 +1000,7 @@ async def get_source_async( config=self.sdk_configuration, base_url=base_url or "", operation_id="get_source", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -1100,7 +1100,7 @@ def list_sources( config=self.sdk_configuration, base_url=base_url or "", operation_id="list_sources", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -1200,7 +1200,7 @@ async def list_sources_async( config=self.sdk_configuration, base_url=base_url or "", operation_id="list_sources", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -1307,7 +1307,7 @@ def update_source( config=self.sdk_configuration, base_url=base_url or "", operation_id="update_source", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -1414,7 +1414,7 @@ async def update_source_async( config=self.sdk_configuration, base_url=base_url or "", operation_id="update_source", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, diff --git a/src/unstructured_client/utils/__init__.py b/src/unstructured_client/utils/__init__.py index dc88403b..56164cf3 100644 --- a/src/unstructured_client/utils/__init__.py +++ b/src/unstructured_client/utils/__init__.py @@ -3,6 +3,7 @@ from typing import TYPE_CHECKING from importlib import import_module import builtins +import sys if TYPE_CHECKING: from .annotations import get_discriminator @@ -159,6 +160,18 @@ } +def dynamic_import(modname, retries=3): + for attempt in range(retries): + try: + return import_module(modname, __package__) + except KeyError: + # Clear any half-initialized module and retry + sys.modules.pop(modname, None) + if attempt == retries - 1: + break + raise KeyError(f"Failed to import module '{modname}' after {retries} attempts") + + def __getattr__(attr_name: str) -> object: module_name = _dynamic_imports.get(attr_name) if module_name is None: @@ -167,9 +180,8 @@ def __getattr__(attr_name: str) -> object: ) try: - module = import_module(module_name, __package__) - result = getattr(module, attr_name) - return result + module = dynamic_import(module_name) + return getattr(module, attr_name) except ImportError as e: raise ImportError( f"Failed to import {attr_name} from {module_name}: {e}" diff --git a/src/unstructured_client/utils/annotations.py b/src/unstructured_client/utils/annotations.py index 387874ed..12e0aa4f 100644 --- a/src/unstructured_client/utils/annotations.py +++ b/src/unstructured_client/utils/annotations.py @@ -3,6 +3,7 @@ from enum import Enum from typing import Any, Optional + def get_discriminator(model: Any, fieldname: str, key: str) -> str: """ Recursively search for the discriminator attribute in a model. @@ -25,31 +26,54 @@ def get_field_discriminator(field: Any) -> Optional[str]: if isinstance(field, dict): if key in field: - return f'{field[key]}' + return f"{field[key]}" if hasattr(field, fieldname): attr = getattr(field, fieldname) if isinstance(attr, Enum): - return f'{attr.value}' - return f'{attr}' + return f"{attr.value}" + return f"{attr}" if hasattr(field, upper_fieldname): attr = getattr(field, upper_fieldname) if isinstance(attr, Enum): - return f'{attr.value}' - return f'{attr}' + return f"{attr.value}" + return f"{attr}" return None + def search_nested_discriminator(obj: Any) -> Optional[str]: + """Recursively search for discriminator in nested structures.""" + # First try direct field lookup + discriminator = get_field_discriminator(obj) + if discriminator is not None: + return discriminator + + # If it's a dict, search in nested values + if isinstance(obj, dict): + for value in obj.values(): + if isinstance(value, list): + # Search in list items + for item in value: + nested_discriminator = search_nested_discriminator(item) + if nested_discriminator is not None: + return nested_discriminator + elif isinstance(value, dict): + # Search in nested dict + nested_discriminator = search_nested_discriminator(value) + if nested_discriminator is not None: + return nested_discriminator + + return None if isinstance(model, list): for field in model: - discriminator = get_field_discriminator(field) + discriminator = search_nested_discriminator(field) if discriminator is not None: return discriminator - discriminator = get_field_discriminator(model) + discriminator = search_nested_discriminator(model) if discriminator is not None: return discriminator - raise ValueError(f'Could not find discriminator field {fieldname} in {model}') + raise ValueError(f"Could not find discriminator field {fieldname} in {model}") diff --git a/src/unstructured_client/utils/eventstreaming.py b/src/unstructured_client/utils/eventstreaming.py index 74a63f75..0969899b 100644 --- a/src/unstructured_client/utils/eventstreaming.py +++ b/src/unstructured_client/utils/eventstreaming.py @@ -17,6 +17,9 @@ class EventStream(Generic[T]): + # Holds a reference to the SDK client to avoid it being garbage collected + # and cause termination of the underlying httpx client. + client_ref: Optional[object] response: httpx.Response generator: Generator[T, None, None] @@ -25,9 +28,11 @@ def __init__( response: httpx.Response, decoder: Callable[[str], T], sentinel: Optional[str] = None, + client_ref: Optional[object] = None, ): self.response = response self.generator = stream_events(response, decoder, sentinel) + self.client_ref = client_ref def __iter__(self): return self @@ -43,6 +48,9 @@ def __exit__(self, exc_type, exc_val, exc_tb): class EventStreamAsync(Generic[T]): + # Holds a reference to the SDK client to avoid it being garbage collected + # and cause termination of the underlying httpx client. + client_ref: Optional[object] response: httpx.Response generator: AsyncGenerator[T, None] @@ -51,9 +59,11 @@ def __init__( response: httpx.Response, decoder: Callable[[str], T], sentinel: Optional[str] = None, + client_ref: Optional[object] = None, ): self.response = response self.generator = stream_events_async(response, decoder, sentinel) + self.client_ref = client_ref def __aiter__(self): return self diff --git a/src/unstructured_client/workflows.py b/src/unstructured_client/workflows.py index 7a2fc6bd..69f8be95 100644 --- a/src/unstructured_client/workflows.py +++ b/src/unstructured_client/workflows.py @@ -81,7 +81,7 @@ def create_workflow( config=self.sdk_configuration, base_url=base_url or "", operation_id="create_workflow", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -184,7 +184,7 @@ async def create_workflow_async( config=self.sdk_configuration, base_url=base_url or "", operation_id="create_workflow", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -284,7 +284,7 @@ def delete_workflow( config=self.sdk_configuration, base_url=base_url or "", operation_id="delete_workflow", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -382,7 +382,7 @@ async def delete_workflow_async( config=self.sdk_configuration, base_url=base_url or "", operation_id="delete_workflow", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -480,7 +480,7 @@ def get_workflow( config=self.sdk_configuration, base_url=base_url or "", operation_id="get_workflow", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -580,7 +580,7 @@ async def get_workflow_async( config=self.sdk_configuration, base_url=base_url or "", operation_id="get_workflow", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -680,7 +680,7 @@ def list_workflows( config=self.sdk_configuration, base_url=base_url or "", operation_id="list_workflows", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -780,7 +780,7 @@ async def list_workflows_async( config=self.sdk_configuration, base_url=base_url or "", operation_id="list_workflows", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -887,7 +887,7 @@ def run_workflow( config=self.sdk_configuration, base_url=base_url or "", operation_id="run_workflow", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -994,7 +994,7 @@ async def run_workflow_async( config=self.sdk_configuration, base_url=base_url or "", operation_id="run_workflow", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -1097,7 +1097,7 @@ def update_workflow( config=self.sdk_configuration, base_url=base_url or "", operation_id="update_workflow", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req, @@ -1200,7 +1200,7 @@ async def update_workflow_async( config=self.sdk_configuration, base_url=base_url or "", operation_id="update_workflow", - oauth2_scopes=[], + oauth2_scopes=None, security_source=self.sdk_configuration.security, ), request=req,