Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: 🐝 Update SDK - Generate #46

Merged
merged 3 commits into from
Mar 2, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions .speakeasy/gen.lock
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
lockVersion: 2.0.0
id: 8b5fa338-9106-4734-abf0-e30d67044a90
management:
docChecksum: 903444f359d1dfa6342c692ae3e5c7ff
docChecksum: a112aea005467aa6818696fa4e99fcfe
docVersion: 0.0.1
speakeasyVersion: internal
generationVersion: 2.250.19
releaseVersion: 0.18.0
configChecksum: 938a4a39baa5695a3140be3b858483d4
generationVersion: 2.277.0
releaseVersion: 0.21.0
configChecksum: c5e7c8526f43272d7585627468d8c4e5
repoURL: https://github.com/Unstructured-IO/unstructured-python-client.git
repoSubDirectory: .
installationURL: https://github.com/Unstructured-IO/unstructured-python-client.git
published: true
features:
python:
core: 4.4.5
core: 4.5.0
examples: 2.81.3
globalSecurity: 2.83.2
globalSecurity: 2.83.4
globalServerURLs: 2.82.1
nameOverrides: 2.81.1
retries: 2.82.1
serverIDs: 2.81.1
unions: 2.82.5
unions: 2.82.6
generatedFiles:
- src/unstructured_client/sdkconfiguration.py
- src/unstructured_client/general.py
@@ -51,3 +51,6 @@ generatedFiles:
- docs/models/shared/security.md
- USAGE.md
- .gitattributes
- src/unstructured_client/_hooks/sdkhooks.py
- src/unstructured_client/_hooks/types.py
- src/unstructured_client/_hooks/__init__.py
32 changes: 31 additions & 1 deletion RELEASES.md
Original file line number Diff line number Diff line change
@@ -424,4 +424,34 @@ Based on:
### Generated
- [python v0.18.0] .
### Releases
- [PyPI v0.18.0] https://pypi.org/project/unstructured-client/0.18.0 - .
- [PyPI v0.18.0] https://pypi.org/project/unstructured-client/0.18.0 - .

## 2024-02-19 00:19:41
### Changes
Based on:
- OpenAPI Doc 0.0.64
- Speakeasy CLI 1.183.2 (2.262.2) https://github.com/speakeasy-api/speakeasy
### Generated
- [python v0.19.0] .
### Releases
- [PyPI v0.19.0] https://pypi.org/project/unstructured-client/0.19.0 - .

## 2024-02-22 00:18:37
### Changes
Based on:
- OpenAPI Doc 0.0.1
- Speakeasy CLI 1.189.0 (2.263.3) https://github.com/speakeasy-api/speakeasy
### Generated
- [python v0.20.0] .
### Releases
- [PyPI v0.20.0] https://pypi.org/project/unstructured-client/0.20.0 - .

## 2024-03-01 23:20:07
### Changes
Based on:
- OpenAPI Doc 0.0.1
- Speakeasy CLI 1.200.0 (2.277.0) https://github.com/speakeasy-api/speakeasy
### Generated
- [python v0.21.0] .
### Releases
- [PyPI v0.21.0] https://pypi.org/project/unstructured-client/0.21.0 - .
9 changes: 2 additions & 7 deletions USAGE.md
Original file line number Diff line number Diff line change
@@ -15,10 +15,6 @@ req = shared.PartitionParameters(
'image',
'table',
],
files=shared.Files(
content='0x2cC94b2FEF'.encode(),
file_name='um.shtml',
),
gz_uncompressed_content_type='application/pdf',
hi_res_model_name='yolox',
languages=[
@@ -31,9 +27,8 @@ req = shared.PartitionParameters(
max_characters=1500,
new_after_n_chars=1500,
output_format='application/json',
skip_infer_table_types=[
'pdf',
],
overlap=25,
overlap_all=True,
strategy='hi_res',
)

4 changes: 3 additions & 1 deletion docs/models/shared/partitionparameters.md

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion gen.yaml
Original file line number Diff line number Diff line change
@@ -7,8 +7,14 @@ generation:
nameResolutionDec2023: false
parameterOrderingFeb2024: false
requestResponseComponentNamesFeb2024: false
auth:
oAuth2ClientCredentialsEnabled: false
python:
version: 0.18.0
version: 0.21.0
additionalDependencies:
dependencies: {}
extraDependencies:
dev: {}
author: Unstructured
clientServerStatusCodesAsErrors: true
description: Python Client SDK for Unstructured API
3 changes: 2 additions & 1 deletion pylintrc
Original file line number Diff line number Diff line change
@@ -179,7 +179,8 @@ good-names=i,
k,
ex,
Run,
_
_,
e

# Good variable names regexes, separated by a comma. If names match any regex,
# they will always be accepted
10 changes: 6 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@

setuptools.setup(
name="unstructured-client",
version="0.18.0",
version="0.21.0",
author="Unstructured",
description="Python Client SDK for Unstructured API",
license = "MIT",
@@ -20,9 +20,9 @@
install_requires=[
"certifi>=2023.7.22",
"charset-normalizer>=3.2.0",
"dataclasses-json-speakeasy>=0.5.11",
"dataclasses-json>=0.6.4",
"idna>=3.4",
"jsonpath-python>=1.0.6 ",
"jsonpath-python>=1.0.6",
"marshmallow>=3.19.0",
"mypy-extensions>=1.0.0",
"packaging>=23.1",
@@ -34,7 +34,9 @@
"urllib3>=1.26.18",
],
extras_require={
"dev":["pylint==2.16.2"]
"dev": [
"pylint==2.16.2",
],
},
package_dir={'': 'src'},
python_requires='>=3.8',
4 changes: 4 additions & 0 deletions src/unstructured_client/_hooks/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT."""

from .sdkhooks import *
from .types import *
55 changes: 55 additions & 0 deletions src/unstructured_client/_hooks/sdkhooks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT."""

import requests
from .types import SDKInitHook, BeforeRequestContext, BeforeRequestHook, AfterSuccessContext, AfterSuccessHook, AfterErrorContext, AfterErrorHook, Hooks
from typing import List, Optional, Tuple, Union


class SDKHooks(Hooks):
sdk_init_hooks: List[SDKInitHook] = []
before_request_hooks: List[BeforeRequestHook] = []
after_success_hooks: List[AfterSuccessHook] = []
after_error_hooks: List[AfterErrorHook] = []

def __init__(self):
pass

def register_sdk_init_hook(self, hook: SDKInitHook) -> None:
self.sdk_init_hooks.append(hook)

def register_before_request_hook(self, hook: BeforeRequestHook) -> None:
self.before_request_hooks.append(hook)

def register_after_success_hook(self, hook: AfterSuccessHook) -> None:
self.after_success_hooks.append(hook)

def register_after_error_hook(self, hook: AfterErrorHook) -> None:
self.after_error_hooks.append(hook)

def sdk_init(self, base_url: str, client: requests.Session) -> Tuple[str, requests.Session]:
for hook in self.sdk_init_hooks:
base_url, client = hook.sdk_init(base_url, client)
return base_url, client

def before_request(self, hook_ctx: BeforeRequestContext, request: requests.PreparedRequest) -> Union[requests.PreparedRequest, Exception]:
for hook in self.before_request_hooks:
request = hook.before_request(hook_ctx, request)
if isinstance(request, Exception):
raise request

return request

def after_success(self, hook_ctx: AfterSuccessContext, response: requests.Response) -> requests.Response:
for hook in self.after_success_hooks:
response = hook.after_success(hook_ctx, response)
if isinstance(response, Exception):
raise response
return response

def after_error(self, hook_ctx: AfterErrorContext, response: Optional[requests.Response], error: Optional[Exception]) -> Tuple[Optional[requests.Response], Optional[Exception]]:
for hook in self.after_error_hooks:
result = hook.after_error(hook_ctx, response, error)
if isinstance(result, Exception):
raise result
response, error = result
return response, error
70 changes: 70 additions & 0 deletions src/unstructured_client/_hooks/types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT."""

import requests as requests_http
from abc import ABC, abstractmethod
from typing import Any, Callable, List, Optional, Tuple, Union


class HookContext:
operation_id: str
oauth2_scopes: Optional[List[str]] = None
security_source: Optional[Union[Any, Callable[[], Any]]] = None

def __init__(self, operation_id: str, oauth2_scopes: Optional[List[str]], security_source: Optional[Union[Any, Callable[[], Any]]]):
self.operation_id = operation_id
self.oauth2_scopes = oauth2_scopes
self.security_source = security_source


class BeforeRequestContext(HookContext):
pass


class AfterSuccessContext(HookContext):
pass


class AfterErrorContext(HookContext):
pass


class SDKInitHook(ABC):
@abstractmethod
def sdk_init(self, base_url: str, client: requests_http.Session) -> Tuple[str, requests_http.Session]:
pass


class BeforeRequestHook(ABC):
@abstractmethod
def before_request(self, hook_ctx: BeforeRequestContext, request: requests_http.PreparedRequest) -> Union[requests_http.PreparedRequest, Exception]:
pass


class AfterSuccessHook(ABC):
@abstractmethod
def after_success(self, hook_ctx: AfterSuccessContext, response: requests_http.Response) -> Union[requests_http.PreparedRequest, Exception]:
pass


class AfterErrorHook(ABC):
@abstractmethod
def after_error(self, hook_ctx: AfterErrorContext, response: Optional[requests_http.Response], error: Optional[Exception]) -> Union[Tuple[Optional[requests_http.PreparedRequest], Optional[Exception]], Exception]:
pass


class Hooks(ABC):
@abstractmethod
def register_sdk_init_hook(self, hook: SDKInitHook):
pass

@abstractmethod
def register_before_request_hook(self, hook: BeforeRequestHook):
pass

@abstractmethod
def register_after_success_hook(self, hook: AfterSuccessHook):
pass

@abstractmethod
def register_after_error_hook(self, hook: AfterErrorHook):
pass
32 changes: 29 additions & 3 deletions src/unstructured_client/general.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT."""

import requests as requests_http
from .sdkconfiguration import SDKConfiguration
from typing import Any, List, Optional
from unstructured_client import utils
from unstructured_client._hooks import HookContext
from unstructured_client.models import errors, operations, shared
from unstructured_client.utils._human_utils import suggest_defining_url_if_401 # human code

@@ -13,15 +15,17 @@ def __init__(self, sdk_config: SDKConfiguration) -> None:
self.sdk_configuration = sdk_config



@suggest_defining_url_if_401 # human code
def partition(self, request: Optional[shared.PartitionParameters], retries: Optional[utils.RetryConfig] = None) -> operations.PartitionResponse:
r"""Pipeline 1"""
hook_ctx = HookContext(operation_id='partition', oauth2_scopes=[], security_source=self.sdk_configuration.security)
base_url = utils.template_url(*self.sdk_configuration.get_server_details())

url = base_url + '/general/v0/general'
headers = {}
req_content_type, data, form = utils.serialize_request_body(request, Optional[shared.PartitionParameters], "request", False, True, 'multipart')
if req_content_type not in ('multipart/form-data', 'multipart/mixed'):
if req_content_type is not None and req_content_type not in ('multipart/form-data', 'multipart/mixed'):
headers['content-type'] = req_content_type
headers['Accept'] = 'application/json'
headers['user-agent'] = self.sdk_configuration.user_agent
@@ -31,6 +35,7 @@ def partition(self, request: Optional[shared.PartitionParameters], retries: Opti
else:
client = utils.configure_security_client(self.sdk_configuration.client, self.sdk_configuration.security)


global_retry_config = self.sdk_configuration.retry_config
retry_config = retries
if retry_config is None:
@@ -40,11 +45,32 @@ def partition(self, request: Optional[shared.PartitionParameters], retries: Opti
retry_config = utils.RetryConfig('backoff', utils.BackoffStrategy(500, 60000, 1.5, 900000), True)

def do_request():
return client.request('POST', url, data=data, files=form, headers=headers)
try:
req = self.sdk_configuration.get_hooks().before_request(
hook_ctx,
requests_http.Request('POST', url, data=data, files=form, headers=headers).prepare(),
)
http_res = client.send(req)
except Exception as e:
_, e = self.sdk_configuration.get_hooks().after_error(hook_ctx, None, e)
raise e

if utils.match_status_codes(['422','4XX','5XX'], http_res.status_code):
http_res, e = self.sdk_configuration.get_hooks().after_error(hook_ctx, http_res, None)
if e:
raise e
else:
result = self.sdk_configuration.get_hooks().after_success(hook_ctx, http_res)
if isinstance(result, Exception):
raise result
http_res = result

return http_res

http_res = utils.retry(do_request, utils.Retries(retry_config, [
'5xx'
]))

content_type = http_res.headers.get('Content-Type')

res = operations.PartitionResponse(status_code=http_res.status_code, content_type=content_type, raw_response=http_res)
@@ -67,4 +93,4 @@ def do_request():

return res


4 changes: 4 additions & 0 deletions src/unstructured_client/models/shared/partition_parameters.py
Original file line number Diff line number Diff line change
@@ -43,6 +43,10 @@ class PartitionParameters:
r"""If chunking strategy is set, cut off new sections after reaching a length of n chars (soft max). Default: 1500"""
output_format: Optional[str] = dataclasses.field(default=None, metadata={'multipart_form': { 'field_name': 'output_format' }})
r"""The format of the response. Supported formats are application/json and text/csv. Default: application/json."""
overlap: Optional[int] = dataclasses.field(default=None, metadata={'multipart_form': { 'field_name': 'overlap' }})
r"""A prefix of this many trailing characters from prior text-split chunk is applied to second and later chunks formed from oversized elements by text-splitting. Default: None"""
overlap_all: Optional[bool] = dataclasses.field(default=None, metadata={'multipart_form': { 'field_name': 'overlap_all' }})
r"""When True, overlap is also applied to 'normal' chunks formed by combining whole elements. Use with caution as this can introduce noise into otherwise clean semantic units. Default: None"""
pdf_infer_table_structure: Optional[bool] = dataclasses.field(default=None, metadata={'multipart_form': { 'field_name': 'pdf_infer_table_structure' }})
r"""If True and strategy=hi_res, any Table Elements extracted from a PDF will include an additional metadata field, 'text_as_html', where the value (string) is a just a transformation of the data into an HTML <table>."""
skip_infer_table_types: Optional[List[str]] = dataclasses.field(default=None, metadata={'multipart_form': { 'field_name': 'skip_infer_table_types' }})
11 changes: 11 additions & 0 deletions src/unstructured_client/sdk.py
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
from .sdkconfiguration import SDKConfiguration
from typing import Callable, Dict, Union
from unstructured_client import utils
from unstructured_client._hooks import SDKHooks
from unstructured_client.models import shared
from unstructured_client.utils._human_utils import clean_server_url # human code

@@ -52,6 +53,16 @@ def security():
server_url = utils.template_url(server_url, url_params)

self.sdk_configuration = SDKConfiguration(client, security, server_url, server, retry_config=retry_config)

hooks = SDKHooks()

current_server_url, *_ = self.sdk_configuration.get_server_details()
server_url, self.sdk_configuration.client = hooks.sdk_init(current_server_url, self.sdk_configuration.client)
if current_server_url != server_url:
self.sdk_configuration.server_url = server_url

# pylint: disable=protected-access
self.sdk_configuration._hooks=hooks

self._init_sdks()

23 changes: 15 additions & 8 deletions src/unstructured_client/sdkconfiguration.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
"""Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT."""

import requests
from dataclasses import dataclass
from typing import Dict, Tuple, Callable, Union
from .utils.retries import RetryConfig

import requests as requests_http
from ._hooks import SDKHooks
from .utils import utils
from .utils.retries import RetryConfig
from dataclasses import dataclass
from typing import Callable, Dict, Tuple, Union
from unstructured_client.models import shared


@@ -21,16 +23,17 @@

@dataclass
class SDKConfiguration:
client: requests.Session
client: requests_http.Session
security: Union[shared.Security,Callable[[], shared.Security]] = None
server_url: str = ''
server: str = ''
language: str = 'python'
openapi_doc_version: str = '0.0.1'
sdk_version: str = '0.18.0'
gen_version: str = '2.250.19'
user_agent: str = 'speakeasy-sdk/python 0.18.0 2.250.19 0.0.1 unstructured-client'
sdk_version: str = '0.21.0'
gen_version: str = '2.277.0'
user_agent: str = 'speakeasy-sdk/python 0.21.0 2.277.0 0.0.1 unstructured-client'
retry_config: RetryConfig = None
_hooks: SDKHooks = None

def get_server_details(self) -> Tuple[str, Dict[str, str]]:
if self.server_url:
@@ -39,3 +42,7 @@ def get_server_details(self) -> Tuple[str, Dict[str, str]]:
self.server = SERVER_PROD

return SERVERS[self.server], {}


def get_hooks(self) -> SDKHooks:
return self._hooks
44 changes: 30 additions & 14 deletions src/unstructured_client/utils/utils.py
Original file line number Diff line number Diff line change
@@ -21,15 +21,16 @@
class SecurityClient:
client: requests.Session
query_params: Dict[str, str] = {}
headers: Dict[str, str] = {}

def __init__(self, client: requests.Session):
self.client = client

def request(self, method, url, **kwargs):
params = kwargs.get('params', {})
kwargs["params"] = {**self.query_params, **params}
def send(self, request: requests.PreparedRequest, **kwargs):
request.prepare_url(url=request.url, params=self.query_params)
request.headers.update(self.headers)

return self.client.request(method, url, **kwargs)
return self.client.send(request, **kwargs)


def configure_security_client(client: requests.Session, security: dataclass):
@@ -102,20 +103,19 @@ def _parse_security_scheme_value(client: SecurityClient, scheme_metadata: Dict,

if scheme_type == "apiKey":
if sub_type == 'header':
client.client.headers[header_name] = value
client.headers[header_name] = value
elif sub_type == 'query':
client.query_params[header_name] = value
elif sub_type == 'cookie':
client.client.cookies[header_name] = value
else:
raise Exception('not supported')
elif scheme_type == "openIdConnect":
client.client.headers[header_name] = _apply_bearer(value)
client.headers[header_name] = _apply_bearer(value)
elif scheme_type == 'oauth2':
client.client.headers[header_name] = _apply_bearer(value)
if sub_type != 'client_credentials':
client.headers[header_name] = _apply_bearer(value)
elif scheme_type == 'http':
if sub_type == 'bearer':
client.client.headers[header_name] = _apply_bearer(value)
client.headers[header_name] = _apply_bearer(value)
else:
raise Exception('not supported')
else:
@@ -145,7 +145,7 @@ def _parse_basic_auth_scheme(client: SecurityClient, scheme: dataclass):
password = value

data = f'{username}:{password}'.encode()
client.client.headers['Authorization'] = f'Basic {base64.b64encode(data).decode()}'
client.headers['Authorization'] = f'Basic {base64.b64encode(data).decode()}'


def generate_url(clazz: type, server_url: str, path: str, path_params: dataclass,
@@ -264,7 +264,8 @@ def get_query_params(clazz: type, query_params: dataclass, gbls: Dict[str, Dict[
f_name = metadata.get("field_name")
serialization = metadata.get('serialization', '')
if serialization != '':
serialized_parms = _get_serialized_params(metadata, field.type, f_name, value)
serialized_parms = _get_serialized_params(
metadata, field.type, f_name, value)
for key, value in serialized_parms.items():
if key in params:
params[key].extend(value)
@@ -312,7 +313,8 @@ def _get_serialized_params(metadata: Dict, field_type: type, field_name: str, ob

serialization = metadata.get('serialization', '')
if serialization == 'json':
params[metadata.get("field_name", field_name)] = marshal_json(obj, field_type)
params[metadata.get("field_name", field_name)
] = marshal_json(obj, field_type)

return params

@@ -702,7 +704,8 @@ def unmarshal_json(data, typ, decoder=None):

def marshal_json(val, typ, encoder=None):
if not is_optional_type(typ) and val is None:
raise ValueError(f"Could not marshal None into non-optional type: {typ}")
raise ValueError(
f"Could not marshal None into non-optional type: {typ}")

marshal = make_dataclass('Marshal', [('res', typ)],
bases=(DataClassJsonMixin,))
@@ -732,6 +735,16 @@ def match_content_type(content_type: str, pattern: str) -> boolean:
return False


def match_status_codes(status_codes: List[str], status_code: int) -> bool:
for code in status_codes:
if code == str(status_code):
return True

if code.endswith("XX") and code.startswith(str(status_code)[:1]):
return True
return False


def datetimeisoformat(optional: bool):
def isoformatoptional(val):
if optional and val is None:
@@ -835,13 +848,15 @@ def list_decode(val: List):

return list_decode


def union_encoder(all_encoders: Dict[str, Callable]):
def selective_encoder(val: any):
if type(val) in all_encoders:
return all_encoders[type(val)](val)
return val
return selective_encoder


def union_decoder(all_decoders: List[Callable]):
def selective_decoder(val: any):
decoded = val
@@ -854,6 +869,7 @@ def selective_decoder(val: any):
return decoded
return selective_decoder


def get_field_name(name):
def override(_, _field_name=name):
return _field_name