cliV1 0.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cliv1-0.1.1.dist-info/METADATA +156 -0
- cliv1-0.1.1.dist-info/RECORD +83 -0
- cliv1-0.1.1.dist-info/WHEEL +4 -0
- cliv1-0.1.1.dist-info/licenses/LICENSE +21 -0
- swagger_petstore_open_api_3_0/__init__.py +15 -0
- swagger_petstore_open_api_3_0/apis/__init__.py +5 -0
- swagger_petstore_open_api_3_0/apis/pet_api.py +881 -0
- swagger_petstore_open_api_3_0/apis/store.py +411 -0
- swagger_petstore_open_api_3_0/apis/user_api.py +792 -0
- swagger_petstore_open_api_3_0/async_client.py +79 -0
- swagger_petstore_open_api_3_0/auth.py +17 -0
- swagger_petstore_open_api_3_0/base_client.py +18 -0
- swagger_petstore_open_api_3_0/client.py +77 -0
- swagger_petstore_open_api_3_0/core/__init__.py +342 -0
- swagger_petstore_open_api_3_0/core/_internal/__init__.py +7 -0
- swagger_petstore_open_api_3_0/core/_internal/content_disposition.py +154 -0
- swagger_petstore_open_api_3_0/core/_internal/flattening.py +139 -0
- swagger_petstore_open_api_3_0/core/_internal/headers.py +144 -0
- swagger_petstore_open_api_3_0/core/_internal/urls.py +166 -0
- swagger_petstore_open_api_3_0/core/_internal/wire.py +173 -0
- swagger_petstore_open_api_3_0/core/adapters.py +177 -0
- swagger_petstore_open_api_3_0/core/auth/__init__.py +70 -0
- swagger_petstore_open_api_3_0/core/auth/composition.py +175 -0
- swagger_petstore_open_api_3_0/core/auth/models.py +217 -0
- swagger_petstore_open_api_3_0/core/auth/protocols.py +103 -0
- swagger_petstore_open_api_3_0/core/auth/schemes/__init__.py +94 -0
- swagger_petstore_open_api_3_0/core/auth/schemes/api_key_auth.py +53 -0
- swagger_petstore_open_api_3_0/core/auth/schemes/basic_auth.py +73 -0
- swagger_petstore_open_api_3_0/core/auth/schemes/bearer_auth.py +21 -0
- swagger_petstore_open_api_3_0/core/auth/schemes/oauth2_authorization_code.py +393 -0
- swagger_petstore_open_api_3_0/core/auth/schemes/oauth2_client_credentials.py +127 -0
- swagger_petstore_open_api_3_0/core/auth/schemes/oauth2_password.py +142 -0
- swagger_petstore_open_api_3_0/core/auth/schemes/oauth2_schemes.py +300 -0
- swagger_petstore_open_api_3_0/core/base_raw_response.py +49 -0
- swagger_petstore_open_api_3_0/core/bodies.py +563 -0
- swagger_petstore_open_api_3_0/core/converters/__init__.py +68 -0
- swagger_petstore_open_api_3_0/core/converters/date_time.py +237 -0
- swagger_petstore_open_api_3_0/core/converters/encoded_bytes.py +271 -0
- swagger_petstore_open_api_3_0/core/converters/open_enum.py +35 -0
- swagger_petstore_open_api_3_0/core/decoding.py +263 -0
- swagger_petstore_open_api_3_0/core/exceptions.py +41 -0
- swagger_petstore_open_api_3_0/core/file_responses.py +324 -0
- swagger_petstore_open_api_3_0/core/files.py +173 -0
- swagger_petstore_open_api_3_0/core/httpx_transport.py +766 -0
- swagger_petstore_open_api_3_0/core/models.py +143 -0
- swagger_petstore_open_api_3_0/core/optionality.py +130 -0
- swagger_petstore_open_api_3_0/core/params.py +161 -0
- swagger_petstore_open_api_3_0/core/raw_client.py +388 -0
- swagger_petstore_open_api_3_0/core/request_options.py +94 -0
- swagger_petstore_open_api_3_0/core/results.py +110 -0
- swagger_petstore_open_api_3_0/core/runtime_env.py +43 -0
- swagger_petstore_open_api_3_0/core/servers.py +33 -0
- swagger_petstore_open_api_3_0/core/transport.py +248 -0
- swagger_petstore_open_api_3_0/errors/__init__.py +48 -0
- swagger_petstore_open_api_3_0/errors/add_pet_error.py +21 -0
- swagger_petstore_open_api_3_0/errors/delete_order_error.py +21 -0
- swagger_petstore_open_api_3_0/errors/delete_pet_error.py +21 -0
- swagger_petstore_open_api_3_0/errors/delete_user_error.py +21 -0
- swagger_petstore_open_api_3_0/errors/find_pets_by_status_error.py +21 -0
- swagger_petstore_open_api_3_0/errors/find_pets_by_tags_error.py +21 -0
- swagger_petstore_open_api_3_0/errors/get_order_by_id_error.py +21 -0
- swagger_petstore_open_api_3_0/errors/get_pet_by_id_error.py +21 -0
- swagger_petstore_open_api_3_0/errors/get_user_by_name_error.py +21 -0
- swagger_petstore_open_api_3_0/errors/login_user_error.py +21 -0
- swagger_petstore_open_api_3_0/errors/place_order_error.py +21 -0
- swagger_petstore_open_api_3_0/errors/update_pet_error.py +21 -0
- swagger_petstore_open_api_3_0/errors/update_pet_with_form_error.py +21 -0
- swagger_petstore_open_api_3_0/errors/update_user_error.py +21 -0
- swagger_petstore_open_api_3_0/errors/upload_file_error.py +21 -0
- swagger_petstore_open_api_3_0/models/__init__.py +23 -0
- swagger_petstore_open_api_3_0/models/api_response.py +18 -0
- swagger_petstore_open_api_3_0/models/category.py +15 -0
- swagger_petstore_open_api_3_0/models/enums/__init__.py +4 -0
- swagger_petstore_open_api_3_0/models/enums/order_status.py +17 -0
- swagger_petstore_open_api_3_0/models/enums/pet_status.py +17 -0
- swagger_petstore_open_api_3_0/models/order.py +27 -0
- swagger_petstore_open_api_3_0/models/pet.py +28 -0
- swagger_petstore_open_api_3_0/models/tag.py +15 -0
- swagger_petstore_open_api_3_0/models/user.py +29 -0
- swagger_petstore_open_api_3_0/py.typed +0 -0
- swagger_petstore_open_api_3_0/server/__init__.py +21 -0
- swagger_petstore_open_api_3_0/server/server.py +17 -0
- swagger_petstore_open_api_3_0/server/server_config.py +52 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from functools import cached_property
|
|
4
|
+
from types import TracebackType
|
|
5
|
+
|
|
6
|
+
from typing_extensions import Self
|
|
7
|
+
|
|
8
|
+
from .apis.pet_api import AsyncPetApi
|
|
9
|
+
from .apis.store import AsyncStore
|
|
10
|
+
from .apis.user_api import AsyncUserApi
|
|
11
|
+
from .auth import AsyncAuthSchemes
|
|
12
|
+
from .base_client import DEFAULT_TIMEOUT, BaseSwaggerPetstoreOpenApi30Client
|
|
13
|
+
from .core import (
|
|
14
|
+
OPERATING_SYSTEM,
|
|
15
|
+
PYTHON_RUNTIME,
|
|
16
|
+
ApiKeyHeaderScheme,
|
|
17
|
+
AsyncHttpClient,
|
|
18
|
+
AsyncHttpxClient,
|
|
19
|
+
AsyncRawClient,
|
|
20
|
+
no_auth,
|
|
21
|
+
param,
|
|
22
|
+
)
|
|
23
|
+
from .server.server_config import ServerConfigOrDict
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class AsyncSwaggerPetstoreOpenApi30Client(BaseSwaggerPetstoreOpenApi30Client[AsyncRawClient]):
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
*,
|
|
30
|
+
server_config: ServerConfigOrDict | None = None,
|
|
31
|
+
timeout: float = DEFAULT_TIMEOUT,
|
|
32
|
+
custom_async_http_client: AsyncHttpClient | None = None,
|
|
33
|
+
petstore_auth: str | None = None,
|
|
34
|
+
api_key: str | None = None,
|
|
35
|
+
) -> None:
|
|
36
|
+
super().__init__(server_config=server_config, timeout=timeout)
|
|
37
|
+
self._raw_client = AsyncRawClient(
|
|
38
|
+
http_client=(
|
|
39
|
+
custom_async_http_client if custom_async_http_client is not None else AsyncHttpxClient(timeout=timeout)
|
|
40
|
+
),
|
|
41
|
+
global_headers=[
|
|
42
|
+
param[str]("User-Agent", "SwaggerPetstoreOpenApi30Client/1.0.26 Python"),
|
|
43
|
+
param[str]("X-APIMatic-Lang", "Python"),
|
|
44
|
+
param[str]("X-APIMatic-Package-Version", "1.0.26"),
|
|
45
|
+
param[str]("X-APIMatic-Gen-Version", "4.0.0"),
|
|
46
|
+
param[str]("X-APIMatic-OS", OPERATING_SYSTEM),
|
|
47
|
+
param[str]("X-APIMatic-Runtime", PYTHON_RUNTIME),
|
|
48
|
+
],
|
|
49
|
+
)
|
|
50
|
+
self._auth = AsyncAuthSchemes(
|
|
51
|
+
petstore_auth=ApiKeyHeaderScheme("Authorization", petstore_auth) if petstore_auth is not None else no_auth,
|
|
52
|
+
api_key=ApiKeyHeaderScheme("api_key", api_key) if api_key is not None else no_auth,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
@cached_property
|
|
56
|
+
def pet_api(self) -> AsyncPetApi:
|
|
57
|
+
return AsyncPetApi(self._raw_client, self._server, self._auth)
|
|
58
|
+
|
|
59
|
+
@cached_property
|
|
60
|
+
def store(self) -> AsyncStore:
|
|
61
|
+
return AsyncStore(self._raw_client, self._server, self._auth)
|
|
62
|
+
|
|
63
|
+
@cached_property
|
|
64
|
+
def user_api(self) -> AsyncUserApi:
|
|
65
|
+
return AsyncUserApi(self._raw_client, self._server)
|
|
66
|
+
|
|
67
|
+
async def aclose(self) -> None:
|
|
68
|
+
await self._raw_client.http_client.aclose()
|
|
69
|
+
|
|
70
|
+
async def __aenter__(self) -> Self:
|
|
71
|
+
return self
|
|
72
|
+
|
|
73
|
+
async def __aexit__(
|
|
74
|
+
self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_tb: TracebackType | None
|
|
75
|
+
) -> None:
|
|
76
|
+
await self.aclose()
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
AsyncClient = AsyncSwaggerPetstoreOpenApi30Client
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
|
|
5
|
+
from .core import AsyncAuthScheme, AuthScheme
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass(frozen=True, slots=True, kw_only=True)
|
|
9
|
+
class AuthSchemes:
|
|
10
|
+
petstore_auth: AuthScheme
|
|
11
|
+
api_key: AuthScheme
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(frozen=True, slots=True, kw_only=True)
|
|
15
|
+
class AsyncAuthSchemes:
|
|
16
|
+
petstore_auth: AsyncAuthScheme
|
|
17
|
+
api_key: AsyncAuthScheme
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Generic
|
|
4
|
+
|
|
5
|
+
from .core import RawClientT
|
|
6
|
+
from .server.server import Server
|
|
7
|
+
from .server.server_config import ServerConfig, ServerConfigOrDict
|
|
8
|
+
|
|
9
|
+
DEFAULT_TIMEOUT = 30.0
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class BaseSwaggerPetstoreOpenApi30Client(Generic[RawClientT]):
|
|
13
|
+
_raw_client: RawClientT
|
|
14
|
+
|
|
15
|
+
def __init__(self, *, server_config: ServerConfigOrDict | None = None, timeout: float = DEFAULT_TIMEOUT) -> None:
|
|
16
|
+
if not timeout > 0:
|
|
17
|
+
raise ValueError(f"timeout must be greater than 0; got {timeout!r}")
|
|
18
|
+
self._server = Server(ServerConfig.coerce(server_config))
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from functools import cached_property
|
|
4
|
+
from types import TracebackType
|
|
5
|
+
|
|
6
|
+
from typing_extensions import Self
|
|
7
|
+
|
|
8
|
+
from .apis.pet_api import PetApi
|
|
9
|
+
from .apis.store import Store
|
|
10
|
+
from .apis.user_api import UserApi
|
|
11
|
+
from .auth import AuthSchemes
|
|
12
|
+
from .base_client import DEFAULT_TIMEOUT, BaseSwaggerPetstoreOpenApi30Client
|
|
13
|
+
from .core import (
|
|
14
|
+
OPERATING_SYSTEM,
|
|
15
|
+
PYTHON_RUNTIME,
|
|
16
|
+
ApiKeyHeaderScheme,
|
|
17
|
+
HttpClient,
|
|
18
|
+
HttpxClient,
|
|
19
|
+
RawClient,
|
|
20
|
+
no_auth,
|
|
21
|
+
param,
|
|
22
|
+
)
|
|
23
|
+
from .server.server_config import ServerConfigOrDict
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class SwaggerPetstoreOpenApi30Client(BaseSwaggerPetstoreOpenApi30Client[RawClient]):
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
*,
|
|
30
|
+
server_config: ServerConfigOrDict | None = None,
|
|
31
|
+
timeout: float = DEFAULT_TIMEOUT,
|
|
32
|
+
custom_http_client: HttpClient | None = None,
|
|
33
|
+
petstore_auth: str | None = None,
|
|
34
|
+
api_key: str | None = None,
|
|
35
|
+
) -> None:
|
|
36
|
+
super().__init__(server_config=server_config, timeout=timeout)
|
|
37
|
+
self._raw_client = RawClient(
|
|
38
|
+
http_client=custom_http_client if custom_http_client is not None else HttpxClient(timeout=timeout),
|
|
39
|
+
global_headers=[
|
|
40
|
+
param[str]("User-Agent", "SwaggerPetstoreOpenApi30Client/1.0.26 Python"),
|
|
41
|
+
param[str]("X-APIMatic-Lang", "Python"),
|
|
42
|
+
param[str]("X-APIMatic-Package-Version", "1.0.26"),
|
|
43
|
+
param[str]("X-APIMatic-Gen-Version", "4.0.0"),
|
|
44
|
+
param[str]("X-APIMatic-OS", OPERATING_SYSTEM),
|
|
45
|
+
param[str]("X-APIMatic-Runtime", PYTHON_RUNTIME),
|
|
46
|
+
],
|
|
47
|
+
)
|
|
48
|
+
self._auth = AuthSchemes(
|
|
49
|
+
petstore_auth=ApiKeyHeaderScheme("Authorization", petstore_auth) if petstore_auth is not None else no_auth,
|
|
50
|
+
api_key=ApiKeyHeaderScheme("api_key", api_key) if api_key is not None else no_auth,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
@cached_property
|
|
54
|
+
def pet_api(self) -> PetApi:
|
|
55
|
+
return PetApi(self._raw_client, self._server, self._auth)
|
|
56
|
+
|
|
57
|
+
@cached_property
|
|
58
|
+
def store(self) -> Store:
|
|
59
|
+
return Store(self._raw_client, self._server, self._auth)
|
|
60
|
+
|
|
61
|
+
@cached_property
|
|
62
|
+
def user_api(self) -> UserApi:
|
|
63
|
+
return UserApi(self._raw_client, self._server)
|
|
64
|
+
|
|
65
|
+
def close(self) -> None:
|
|
66
|
+
self._raw_client.http_client.close()
|
|
67
|
+
|
|
68
|
+
def __enter__(self) -> Self:
|
|
69
|
+
return self
|
|
70
|
+
|
|
71
|
+
def __exit__(
|
|
72
|
+
self, exc_type: type[BaseException] | None, exc: BaseException | None, exc_tb: TracebackType | None
|
|
73
|
+
) -> None:
|
|
74
|
+
self.close()
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
Client = SwaggerPetstoreOpenApi30Client
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
"""Public surface of the SDK runtime.
|
|
2
|
+
|
|
3
|
+
Everything the generated layers (``api/``, ``models/``, ``errors/``, ``server/``, the two clients)
|
|
4
|
+
need from the runtime is re-exported here, so a generated module imports from one place --
|
|
5
|
+
``from <sdk>.core import ApiResult, RawClient, json_decoder`` -- instead of reaching into the
|
|
6
|
+
runtime's internal module layout. That indirection is the point: the modules behind this facade are
|
|
7
|
+
free to move without touching a single generated file.
|
|
8
|
+
|
|
9
|
+
A symbol earns a place here by one test: a generator may emit it, or a caller may need to name it.
|
|
10
|
+
Internal machinery the runtime only calls itself -- the adapter cache, the decoder implementation
|
|
11
|
+
classes, the sentinel stripper -- is deliberately absent, and remains reachable at its own module
|
|
12
|
+
path for the unit tests that target it.
|
|
13
|
+
|
|
14
|
+
Everything remains importable from its fully-qualified module path as well."""
|
|
15
|
+
|
|
16
|
+
from .auth import (
|
|
17
|
+
AllSchemes,
|
|
18
|
+
AnySchemes,
|
|
19
|
+
AsyncAllSchemes,
|
|
20
|
+
AsyncAnySchemes,
|
|
21
|
+
AsyncAuthScheme,
|
|
22
|
+
AsyncRefreshableTokenSource,
|
|
23
|
+
AsyncTokenSource,
|
|
24
|
+
AuthParams,
|
|
25
|
+
AuthScheme,
|
|
26
|
+
OAuthError,
|
|
27
|
+
OAuthProviderError,
|
|
28
|
+
OAuthToken,
|
|
29
|
+
OAuthTokenRefreshable,
|
|
30
|
+
RefreshableTokenSource,
|
|
31
|
+
RevocableAuthScheme,
|
|
32
|
+
TokenSource,
|
|
33
|
+
client_secret_basic,
|
|
34
|
+
client_secret_post,
|
|
35
|
+
invalidate,
|
|
36
|
+
is_configured,
|
|
37
|
+
no_auth,
|
|
38
|
+
oauth_error_response,
|
|
39
|
+
resolve_auth,
|
|
40
|
+
)
|
|
41
|
+
from .auth.schemes import (
|
|
42
|
+
ApiKeyCookieScheme,
|
|
43
|
+
ApiKeyHeaderScheme,
|
|
44
|
+
ApiKeyQueryScheme,
|
|
45
|
+
AsyncAuthorizationCodeCredentials,
|
|
46
|
+
AsyncAuthorizationCodeCredentialsDict,
|
|
47
|
+
AsyncAuthorizationCodeCredentialsOrDict,
|
|
48
|
+
AsyncAuthorizationCodePrompt,
|
|
49
|
+
AsyncAuthorizationCodeTokenSource,
|
|
50
|
+
AsyncClientCredentialsTokenSource,
|
|
51
|
+
AsyncOAuth2RefreshableScheme,
|
|
52
|
+
AsyncOAuth2Scheme,
|
|
53
|
+
AsyncPasswordTokenSource,
|
|
54
|
+
AuthorizationCodeCredentials,
|
|
55
|
+
AuthorizationCodeCredentialsDict,
|
|
56
|
+
AuthorizationCodeCredentialsOrDict,
|
|
57
|
+
AuthorizationCodePrompt,
|
|
58
|
+
AuthorizationCodeTokenSource,
|
|
59
|
+
BasicAuthCredentials,
|
|
60
|
+
BasicAuthCredentialsDict,
|
|
61
|
+
BasicAuthCredentialsOrDict,
|
|
62
|
+
BasicAuthScheme,
|
|
63
|
+
BearerAuthScheme,
|
|
64
|
+
ClientCredentials,
|
|
65
|
+
ClientCredentialsDict,
|
|
66
|
+
ClientCredentialsOrDict,
|
|
67
|
+
ClientCredentialsTokenSource,
|
|
68
|
+
OAuth2RefreshableScheme,
|
|
69
|
+
OAuth2Scheme,
|
|
70
|
+
PasswordCredentials,
|
|
71
|
+
PasswordCredentialsDict,
|
|
72
|
+
PasswordCredentialsOrDict,
|
|
73
|
+
PasswordTokenSource,
|
|
74
|
+
PkceMethod,
|
|
75
|
+
)
|
|
76
|
+
from .base_raw_response import BaseRawResponse, SecuredRawResponse
|
|
77
|
+
from .bodies import (
|
|
78
|
+
BinaryBody,
|
|
79
|
+
FormBody,
|
|
80
|
+
JsonBody,
|
|
81
|
+
MultipartBody,
|
|
82
|
+
MultipartFile,
|
|
83
|
+
MultipartPart,
|
|
84
|
+
MultipartText,
|
|
85
|
+
RequestBody,
|
|
86
|
+
TextBody,
|
|
87
|
+
binary_body,
|
|
88
|
+
file_part,
|
|
89
|
+
form_body,
|
|
90
|
+
json_body,
|
|
91
|
+
json_part,
|
|
92
|
+
multipart_body,
|
|
93
|
+
text_body,
|
|
94
|
+
)
|
|
95
|
+
from .converters import (
|
|
96
|
+
Base16AsciiEncodedBytes,
|
|
97
|
+
Base16Cp1252EncodedBytes,
|
|
98
|
+
Base16Latin1EncodedBytes,
|
|
99
|
+
Base16Utf8EncodedBytes,
|
|
100
|
+
Base32AsciiEncodedBytes,
|
|
101
|
+
Base32Cp1252EncodedBytes,
|
|
102
|
+
Base32HexAsciiEncodedBytes,
|
|
103
|
+
Base32HexCp1252EncodedBytes,
|
|
104
|
+
Base32HexLatin1EncodedBytes,
|
|
105
|
+
Base32HexUtf8EncodedBytes,
|
|
106
|
+
Base32Latin1EncodedBytes,
|
|
107
|
+
Base32Utf8EncodedBytes,
|
|
108
|
+
Base64AsciiEncodedBytes,
|
|
109
|
+
Base64Cp1252EncodedBytes,
|
|
110
|
+
Base64Latin1EncodedBytes,
|
|
111
|
+
Base64UrlAsciiEncodedBytes,
|
|
112
|
+
Base64UrlCp1252EncodedBytes,
|
|
113
|
+
Base64UrlLatin1EncodedBytes,
|
|
114
|
+
Base64UrlUtf8EncodedBytes,
|
|
115
|
+
Base64Utf8EncodedBytes,
|
|
116
|
+
ByteField,
|
|
117
|
+
Date,
|
|
118
|
+
RFC1123DateTime,
|
|
119
|
+
RFC3339DateTime,
|
|
120
|
+
UnixSecondsDateTime,
|
|
121
|
+
open_enum_validator,
|
|
122
|
+
)
|
|
123
|
+
from .decoding import (
|
|
124
|
+
AsyncStreamDecoder,
|
|
125
|
+
ErrorMapper,
|
|
126
|
+
ResponseDecoder,
|
|
127
|
+
StreamDecoder,
|
|
128
|
+
async_file_decoder,
|
|
129
|
+
decode_json,
|
|
130
|
+
decode_text,
|
|
131
|
+
empty_response,
|
|
132
|
+
file_decoder,
|
|
133
|
+
json_decoder,
|
|
134
|
+
raw_error_response,
|
|
135
|
+
text_decoder,
|
|
136
|
+
)
|
|
137
|
+
from .exceptions import ApiError
|
|
138
|
+
from .file_responses import AsyncFileResponse, FileResponse
|
|
139
|
+
from .files import (
|
|
140
|
+
AsyncBinaryContent,
|
|
141
|
+
AsyncBinaryReader,
|
|
142
|
+
AsyncFileInput,
|
|
143
|
+
BinaryContent,
|
|
144
|
+
BinaryReader,
|
|
145
|
+
FileInput,
|
|
146
|
+
NamedFile,
|
|
147
|
+
)
|
|
148
|
+
from .httpx_transport import AsyncHttpxClient, HttpxClient
|
|
149
|
+
from .models import SdkBaseModel
|
|
150
|
+
from .optionality import UNSET, Optional, OptionalNullable, UnsetType
|
|
151
|
+
from .params import SerializationFormat, UrlTemplate, param
|
|
152
|
+
from .raw_client import (
|
|
153
|
+
AsyncRawClient,
|
|
154
|
+
RawClient,
|
|
155
|
+
RawClientT,
|
|
156
|
+
)
|
|
157
|
+
from .request_options import RequestOptions, RequestOptionsDict, RequestOptionsOrDict
|
|
158
|
+
from .results import ApiResult, Failure, RawError, Success
|
|
159
|
+
from .runtime_env import OPERATING_SYSTEM, PYTHON_RUNTIME
|
|
160
|
+
from .servers import validate_one_of
|
|
161
|
+
from .transport import (
|
|
162
|
+
AsyncHttpClient,
|
|
163
|
+
AsyncStreamedResponse,
|
|
164
|
+
HttpClient,
|
|
165
|
+
HttpRequest,
|
|
166
|
+
HttpResponse,
|
|
167
|
+
StreamedResponse,
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
__all__ = [
|
|
171
|
+
# Result and error types
|
|
172
|
+
"ApiResult",
|
|
173
|
+
"Success",
|
|
174
|
+
"Failure",
|
|
175
|
+
"RawError",
|
|
176
|
+
"ApiError",
|
|
177
|
+
# HTTP transport
|
|
178
|
+
"HttpClient",
|
|
179
|
+
"AsyncHttpClient",
|
|
180
|
+
"HttpRequest",
|
|
181
|
+
"HttpResponse",
|
|
182
|
+
"HttpxClient",
|
|
183
|
+
"AsyncHttpxClient",
|
|
184
|
+
# Request parameters and bodies
|
|
185
|
+
"param",
|
|
186
|
+
"SerializationFormat",
|
|
187
|
+
"UrlTemplate",
|
|
188
|
+
"RequestBody",
|
|
189
|
+
"JsonBody",
|
|
190
|
+
"json_body",
|
|
191
|
+
"FormBody",
|
|
192
|
+
"form_body",
|
|
193
|
+
"MultipartBody",
|
|
194
|
+
"multipart_body",
|
|
195
|
+
"MultipartPart",
|
|
196
|
+
"MultipartText",
|
|
197
|
+
"MultipartFile",
|
|
198
|
+
"file_part",
|
|
199
|
+
"json_part",
|
|
200
|
+
"BinaryBody",
|
|
201
|
+
"binary_body",
|
|
202
|
+
"TextBody",
|
|
203
|
+
"text_body",
|
|
204
|
+
# File input
|
|
205
|
+
"BinaryReader",
|
|
206
|
+
"AsyncBinaryReader",
|
|
207
|
+
"BinaryContent",
|
|
208
|
+
"AsyncBinaryContent",
|
|
209
|
+
"NamedFile",
|
|
210
|
+
"FileInput",
|
|
211
|
+
"AsyncFileInput",
|
|
212
|
+
# Streamed responses
|
|
213
|
+
"StreamedResponse",
|
|
214
|
+
"AsyncStreamedResponse",
|
|
215
|
+
"FileResponse",
|
|
216
|
+
"AsyncFileResponse",
|
|
217
|
+
# Per-call request options
|
|
218
|
+
"RequestOptions",
|
|
219
|
+
"RequestOptionsDict",
|
|
220
|
+
"RequestOptionsOrDict",
|
|
221
|
+
# Authentication
|
|
222
|
+
"AuthParams",
|
|
223
|
+
"AuthScheme",
|
|
224
|
+
"AsyncAuthScheme",
|
|
225
|
+
"no_auth",
|
|
226
|
+
"is_configured",
|
|
227
|
+
"resolve_auth",
|
|
228
|
+
"BasicAuthCredentials",
|
|
229
|
+
"BasicAuthCredentialsDict",
|
|
230
|
+
"BasicAuthCredentialsOrDict",
|
|
231
|
+
"BasicAuthScheme",
|
|
232
|
+
"BearerAuthScheme",
|
|
233
|
+
"ApiKeyHeaderScheme",
|
|
234
|
+
"ApiKeyQueryScheme",
|
|
235
|
+
"ApiKeyCookieScheme",
|
|
236
|
+
"AnySchemes",
|
|
237
|
+
"AsyncAnySchemes",
|
|
238
|
+
"AllSchemes",
|
|
239
|
+
"AsyncAllSchemes",
|
|
240
|
+
"RevocableAuthScheme",
|
|
241
|
+
"invalidate",
|
|
242
|
+
# Managed OAuth 2.0
|
|
243
|
+
"OAuth2Scheme",
|
|
244
|
+
"AsyncOAuth2Scheme",
|
|
245
|
+
"OAuth2RefreshableScheme",
|
|
246
|
+
"AsyncOAuth2RefreshableScheme",
|
|
247
|
+
"TokenSource",
|
|
248
|
+
"AsyncTokenSource",
|
|
249
|
+
"RefreshableTokenSource",
|
|
250
|
+
"AsyncRefreshableTokenSource",
|
|
251
|
+
"client_secret_basic",
|
|
252
|
+
"client_secret_post",
|
|
253
|
+
"OAuthToken",
|
|
254
|
+
"OAuthTokenRefreshable",
|
|
255
|
+
"OAuthProviderError",
|
|
256
|
+
"OAuthError",
|
|
257
|
+
"oauth_error_response",
|
|
258
|
+
# oauth2 / clientCredentials
|
|
259
|
+
"ClientCredentials",
|
|
260
|
+
"ClientCredentialsDict",
|
|
261
|
+
"ClientCredentialsOrDict",
|
|
262
|
+
"ClientCredentialsTokenSource",
|
|
263
|
+
"AsyncClientCredentialsTokenSource",
|
|
264
|
+
# oauth2 / password
|
|
265
|
+
"PasswordCredentials",
|
|
266
|
+
"PasswordCredentialsDict",
|
|
267
|
+
"PasswordCredentialsOrDict",
|
|
268
|
+
"PasswordTokenSource",
|
|
269
|
+
"AsyncPasswordTokenSource",
|
|
270
|
+
# oauth2 / authorizationCode
|
|
271
|
+
"AuthorizationCodeCredentials",
|
|
272
|
+
"AuthorizationCodeCredentialsDict",
|
|
273
|
+
"AuthorizationCodeCredentialsOrDict",
|
|
274
|
+
"AsyncAuthorizationCodeCredentials",
|
|
275
|
+
"AsyncAuthorizationCodeCredentialsDict",
|
|
276
|
+
"AsyncAuthorizationCodeCredentialsOrDict",
|
|
277
|
+
"AuthorizationCodePrompt",
|
|
278
|
+
"AsyncAuthorizationCodePrompt",
|
|
279
|
+
"PkceMethod",
|
|
280
|
+
"AuthorizationCodeTokenSource",
|
|
281
|
+
"AsyncAuthorizationCodeTokenSource",
|
|
282
|
+
# Response decoding and error mapping
|
|
283
|
+
"ResponseDecoder",
|
|
284
|
+
"ErrorMapper",
|
|
285
|
+
"StreamDecoder",
|
|
286
|
+
"AsyncStreamDecoder",
|
|
287
|
+
"json_decoder",
|
|
288
|
+
"text_decoder",
|
|
289
|
+
"decode_json",
|
|
290
|
+
"decode_text",
|
|
291
|
+
"empty_response",
|
|
292
|
+
"raw_error_response",
|
|
293
|
+
"file_decoder",
|
|
294
|
+
"async_file_decoder",
|
|
295
|
+
# Model base and optionality
|
|
296
|
+
"SdkBaseModel",
|
|
297
|
+
"UNSET",
|
|
298
|
+
"UnsetType",
|
|
299
|
+
"Optional",
|
|
300
|
+
"OptionalNullable",
|
|
301
|
+
# Wire-format converters
|
|
302
|
+
"Date",
|
|
303
|
+
"RFC3339DateTime",
|
|
304
|
+
"RFC1123DateTime",
|
|
305
|
+
"UnixSecondsDateTime",
|
|
306
|
+
# Wire-format binary aliases -- one per (RFC 4648 alphabet, charset) pair
|
|
307
|
+
"Base64AsciiEncodedBytes",
|
|
308
|
+
"Base64Utf8EncodedBytes",
|
|
309
|
+
"Base64Latin1EncodedBytes",
|
|
310
|
+
"Base64Cp1252EncodedBytes",
|
|
311
|
+
"Base64UrlAsciiEncodedBytes",
|
|
312
|
+
"Base64UrlUtf8EncodedBytes",
|
|
313
|
+
"Base64UrlLatin1EncodedBytes",
|
|
314
|
+
"Base64UrlCp1252EncodedBytes",
|
|
315
|
+
"Base32AsciiEncodedBytes",
|
|
316
|
+
"Base32Utf8EncodedBytes",
|
|
317
|
+
"Base32Latin1EncodedBytes",
|
|
318
|
+
"Base32Cp1252EncodedBytes",
|
|
319
|
+
"Base32HexAsciiEncodedBytes",
|
|
320
|
+
"Base32HexUtf8EncodedBytes",
|
|
321
|
+
"Base32HexLatin1EncodedBytes",
|
|
322
|
+
"Base32HexCp1252EncodedBytes",
|
|
323
|
+
"Base16AsciiEncodedBytes",
|
|
324
|
+
"Base16Utf8EncodedBytes",
|
|
325
|
+
"Base16Latin1EncodedBytes",
|
|
326
|
+
"Base16Cp1252EncodedBytes",
|
|
327
|
+
# Binary property declaration
|
|
328
|
+
"ByteField",
|
|
329
|
+
# Open enums
|
|
330
|
+
"open_enum_validator",
|
|
331
|
+
# Raw clients and the raw-response base
|
|
332
|
+
"RawClient",
|
|
333
|
+
"AsyncRawClient",
|
|
334
|
+
"RawClientT",
|
|
335
|
+
"BaseRawResponse",
|
|
336
|
+
"SecuredRawResponse",
|
|
337
|
+
# Host environment reported in the SDK identification headers
|
|
338
|
+
"OPERATING_SYSTEM",
|
|
339
|
+
"PYTHON_RUNTIME",
|
|
340
|
+
# Server layer
|
|
341
|
+
"validate_one_of",
|
|
342
|
+
]
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"""Runtime plumbing.
|
|
2
|
+
|
|
3
|
+
Nothing here is part of the SDK's public surface: these are the pure functions the raw client calls
|
|
4
|
+
to turn parameters into a URL, a header mapping, and form fields. They are grouped under a private
|
|
5
|
+
package so this runtime's own ``__init__`` stays the whole of what generated code imports."""
|
|
6
|
+
|
|
7
|
+
__all__: list[str] = []
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"""``Content-Disposition``, both directions: the filename a response suggests, and the one a
|
|
2
|
+
request carries.
|
|
3
|
+
|
|
4
|
+
One header, one module. The RFC 6266/8187 grammar is the shared asset, so reading it and writing
|
|
5
|
+
it stay together rather than putting one table in two files. ``headers.py`` remains the
|
|
6
|
+
*parameter*-layer module, resolving the outbound layers a caller and the spec contribute; what
|
|
7
|
+
this module renders is a value a body carries, exactly as its media type is.
|
|
8
|
+
|
|
9
|
+
The standard library gets the reading wrong twice, both reproduced during planning
|
|
10
|
+
(docs/plans/file-handling.md, verified facts). ``Message.get_filename()`` returns the plain
|
|
11
|
+
``filename`` when both forms are present -- RFC 6266 §4.3 requires the extended ``filename*`` to
|
|
12
|
+
win -- and the RFC 2231 machinery percent-decodes the extended value as latin-1 whatever charset
|
|
13
|
+
it declares, so the text must be re-encoded through latin-1 and decoded with the declared charset
|
|
14
|
+
to come back intact.
|
|
15
|
+
|
|
16
|
+
The two readers treat their input as attacker-controlled. The parser is **total**: any malformed
|
|
17
|
+
header yields ``None`` rather than raising, because it runs while a streamed connection is held
|
|
18
|
+
and a raise there would leak it. The sanitiser is the paranoid half: a server-suggested name is
|
|
19
|
+
reduced to a basename, stripped of everything Windows refuses, and refused outright when what
|
|
20
|
+
survives is empty, a reserved device name, or too long to create.
|
|
21
|
+
|
|
22
|
+
The writer needs no such paranoia, and by construction rather than by trust: every byte outside
|
|
23
|
+
RFC 8187's ``attr-char`` is percent-encoded, so no name can splice a header and there is nothing
|
|
24
|
+
to refuse."""
|
|
25
|
+
|
|
26
|
+
from __future__ import annotations
|
|
27
|
+
|
|
28
|
+
import re
|
|
29
|
+
from email.message import Message
|
|
30
|
+
from typing import Final
|
|
31
|
+
from urllib.parse import quote
|
|
32
|
+
|
|
33
|
+
_SEPARATORS: Final = re.compile(r"[\\/]")
|
|
34
|
+
_WINDOWS_ILLEGAL: Final = frozenset('<>:"|?*')
|
|
35
|
+
_WINDOWS_RESERVED: Final = frozenset(
|
|
36
|
+
{"CON", "PRN", "AUX", "NUL"} | {f"COM{d}" for d in "123456789"} | {f"LPT{d}" for d in "123456789"}
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def content_disposition_filename(header: str | None) -> str | None:
|
|
41
|
+
"""The filename a ``Content-Disposition`` suggests, or ``None``.
|
|
42
|
+
|
|
43
|
+
Prefers the RFC 8187 extended ``filename*`` (RFC 6266 §4.3) and recovers its text from the
|
|
44
|
+
standard library's latin-1 percent-decode; RFC 8187 §3.2.1 permits only UTF-8, so any other
|
|
45
|
+
declared charset falls back to the plain ``filename`` rather than guessing. Continuation
|
|
46
|
+
segments (``filename*0*``, ``filename*1*``) are collapsed by the same machinery.
|
|
47
|
+
|
|
48
|
+
Total by design: a malformed header returns ``None``, never raises -- this runs between a
|
|
49
|
+
streamed response's head arriving and its owner returning, where a raise would leak the
|
|
50
|
+
connection. The result is *not* trusted as a path; see :func:`safe_filename`.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
header: The header's value, or ``None`` when the response carried none.
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
The suggested filename, or ``None`` when there is no usable one."""
|
|
57
|
+
if header is None:
|
|
58
|
+
return None
|
|
59
|
+
try:
|
|
60
|
+
message = Message()
|
|
61
|
+
message["content-disposition"] = header
|
|
62
|
+
params = message.get_params(header="content-disposition")
|
|
63
|
+
if params is None:
|
|
64
|
+
return None
|
|
65
|
+
|
|
66
|
+
plain: str | None = None
|
|
67
|
+
extended: str | None = None
|
|
68
|
+
for name, raw in params:
|
|
69
|
+
if name != "filename":
|
|
70
|
+
continue
|
|
71
|
+
# The parser hands back a plain parameter as ``str`` and an RFC 2231 extended one as a
|
|
72
|
+
# ``(charset, language, text)`` tuple. A duplicated plain form keeps its first
|
|
73
|
+
# occurrence; duplicated extended forms never reach here -- the stdlib merges them as
|
|
74
|
+
# continuations before ``get_params`` returns.
|
|
75
|
+
value: object = raw
|
|
76
|
+
if isinstance(value, str) and plain is None:
|
|
77
|
+
plain = value
|
|
78
|
+
elif isinstance(value, tuple) and extended is None:
|
|
79
|
+
extended = _decode_extended(value)
|
|
80
|
+
return (extended or plain) or None
|
|
81
|
+
except Exception:
|
|
82
|
+
# Total by design -- the docstring says why. Bad wire data degrades, never raises.
|
|
83
|
+
return None
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _decode_extended(value: tuple[object, ...]) -> str | None:
|
|
87
|
+
# (charset, language, text) -- text percent-decoded as latin-1 by the parser regardless of the
|
|
88
|
+
# declared charset, which is the mojibake the round trip below undoes.
|
|
89
|
+
if len(value) != 3:
|
|
90
|
+
return None
|
|
91
|
+
charset, _language, text = value
|
|
92
|
+
if not isinstance(charset, str) or not isinstance(text, str):
|
|
93
|
+
return None
|
|
94
|
+
if charset.lower() not in ("utf-8", "utf8"):
|
|
95
|
+
return None
|
|
96
|
+
try:
|
|
97
|
+
return text.encode("latin-1").decode("utf-8")
|
|
98
|
+
except (UnicodeEncodeError, UnicodeDecodeError):
|
|
99
|
+
return None
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def render_content_disposition(filename: str) -> str:
|
|
103
|
+
"""The ``Content-Disposition`` value naming a raw request body.
|
|
104
|
+
|
|
105
|
+
RFC 6266's dual form: a quoted ``filename`` holding what a quoted-string can, and, whenever
|
|
106
|
+
that reduction lost something, the RFC 8187 ``filename*`` that did not. A conformant receiver
|
|
107
|
+
prefers the extended parameter (§4.3) and recovers the name exactly; one reading only the plain
|
|
108
|
+
parameter still gets a usable name.
|
|
109
|
+
|
|
110
|
+
Percent-encoding is what makes this safe rather than a character check: every byte outside
|
|
111
|
+
RFC 8187's ``attr-char`` becomes ``%XX``, so a CR, an LF or a ``"`` cannot reach the header
|
|
112
|
+
however the caller spelled the name. There is nothing to refuse.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
filename: The name the caller gave the file, as ``NamedFile.filename`` holds it.
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
The header value -- ``attachment``, and whichever parameters can carry the name."""
|
|
119
|
+
plain = "".join(c for c in filename if c.isascii() and c.isprintable() and c not in '"\\')
|
|
120
|
+
parameters = [f'filename="{plain}"'] if plain else []
|
|
121
|
+
if plain != filename:
|
|
122
|
+
parameters.append(f"filename*=UTF-8''{quote(filename, safe='', encoding='utf-8')}")
|
|
123
|
+
return "; ".join(["attachment", *parameters])
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def safe_filename(filename: str) -> str:
|
|
127
|
+
"""Reduce a server-supplied filename to a name safe to create in a directory.
|
|
128
|
+
|
|
129
|
+
Basename first, under both separator flavours -- ``Content-Disposition`` is
|
|
130
|
+
attacker-controlled and ``filename="../../etc/passwd"`` reaches the parser unchanged -- then
|
|
131
|
+
strip what Windows refuses: ``<>:"|?*``, unprintable characters, and trailing dots or spaces.
|
|
132
|
+
Dropping the colon also neutralises an NTFS alternate-data-stream name. What remains is
|
|
133
|
+
refused rather than mangled when it cannot safely name a file: a reserved device-name stem
|
|
134
|
+
(``CON``, ``NUL``, ``COM1``... -- Windows 10 resolves even ``CON.pdf`` to the console device,
|
|
135
|
+
and a bare ``NUL`` open "succeeds" while the bytes go to the null device) or a name past 255
|
|
136
|
+
characters, the per-component ceiling on NTFS and most POSIX filesystems.
|
|
137
|
+
|
|
138
|
+
Args:
|
|
139
|
+
filename: The server's suggestion, as :func:`content_disposition_filename` returned it.
|
|
140
|
+
|
|
141
|
+
Returns:
|
|
142
|
+
The reduced name, never empty.
|
|
143
|
+
|
|
144
|
+
Raises:
|
|
145
|
+
ValueError: If nothing safe remains -- an empty reduction, ``.`` or ``..``, a reserved
|
|
146
|
+
device name, or a name too long to create."""
|
|
147
|
+
basename = _SEPARATORS.split(filename)[-1]
|
|
148
|
+
cleaned = "".join(ch for ch in basename if ch not in _WINDOWS_ILLEGAL and ch.isprintable())
|
|
149
|
+
cleaned = cleaned.rstrip(". ")
|
|
150
|
+
# A reserved stem is matched as Windows does: up to the first dot, trailing spaces ignored.
|
|
151
|
+
stem = cleaned.split(".", 1)[0].rstrip(" ")
|
|
152
|
+
if not cleaned or stem.upper() in _WINDOWS_RESERVED or len(cleaned) > 255:
|
|
153
|
+
raise ValueError(f"{filename!r} reduces to nothing safe to create -- pass an explicit file path instead")
|
|
154
|
+
return cleaned
|