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.
Files changed (83) hide show
  1. cliv1-0.1.1.dist-info/METADATA +156 -0
  2. cliv1-0.1.1.dist-info/RECORD +83 -0
  3. cliv1-0.1.1.dist-info/WHEEL +4 -0
  4. cliv1-0.1.1.dist-info/licenses/LICENSE +21 -0
  5. swagger_petstore_open_api_3_0/__init__.py +15 -0
  6. swagger_petstore_open_api_3_0/apis/__init__.py +5 -0
  7. swagger_petstore_open_api_3_0/apis/pet_api.py +881 -0
  8. swagger_petstore_open_api_3_0/apis/store.py +411 -0
  9. swagger_petstore_open_api_3_0/apis/user_api.py +792 -0
  10. swagger_petstore_open_api_3_0/async_client.py +79 -0
  11. swagger_petstore_open_api_3_0/auth.py +17 -0
  12. swagger_petstore_open_api_3_0/base_client.py +18 -0
  13. swagger_petstore_open_api_3_0/client.py +77 -0
  14. swagger_petstore_open_api_3_0/core/__init__.py +342 -0
  15. swagger_petstore_open_api_3_0/core/_internal/__init__.py +7 -0
  16. swagger_petstore_open_api_3_0/core/_internal/content_disposition.py +154 -0
  17. swagger_petstore_open_api_3_0/core/_internal/flattening.py +139 -0
  18. swagger_petstore_open_api_3_0/core/_internal/headers.py +144 -0
  19. swagger_petstore_open_api_3_0/core/_internal/urls.py +166 -0
  20. swagger_petstore_open_api_3_0/core/_internal/wire.py +173 -0
  21. swagger_petstore_open_api_3_0/core/adapters.py +177 -0
  22. swagger_petstore_open_api_3_0/core/auth/__init__.py +70 -0
  23. swagger_petstore_open_api_3_0/core/auth/composition.py +175 -0
  24. swagger_petstore_open_api_3_0/core/auth/models.py +217 -0
  25. swagger_petstore_open_api_3_0/core/auth/protocols.py +103 -0
  26. swagger_petstore_open_api_3_0/core/auth/schemes/__init__.py +94 -0
  27. swagger_petstore_open_api_3_0/core/auth/schemes/api_key_auth.py +53 -0
  28. swagger_petstore_open_api_3_0/core/auth/schemes/basic_auth.py +73 -0
  29. swagger_petstore_open_api_3_0/core/auth/schemes/bearer_auth.py +21 -0
  30. swagger_petstore_open_api_3_0/core/auth/schemes/oauth2_authorization_code.py +393 -0
  31. swagger_petstore_open_api_3_0/core/auth/schemes/oauth2_client_credentials.py +127 -0
  32. swagger_petstore_open_api_3_0/core/auth/schemes/oauth2_password.py +142 -0
  33. swagger_petstore_open_api_3_0/core/auth/schemes/oauth2_schemes.py +300 -0
  34. swagger_petstore_open_api_3_0/core/base_raw_response.py +49 -0
  35. swagger_petstore_open_api_3_0/core/bodies.py +563 -0
  36. swagger_petstore_open_api_3_0/core/converters/__init__.py +68 -0
  37. swagger_petstore_open_api_3_0/core/converters/date_time.py +237 -0
  38. swagger_petstore_open_api_3_0/core/converters/encoded_bytes.py +271 -0
  39. swagger_petstore_open_api_3_0/core/converters/open_enum.py +35 -0
  40. swagger_petstore_open_api_3_0/core/decoding.py +263 -0
  41. swagger_petstore_open_api_3_0/core/exceptions.py +41 -0
  42. swagger_petstore_open_api_3_0/core/file_responses.py +324 -0
  43. swagger_petstore_open_api_3_0/core/files.py +173 -0
  44. swagger_petstore_open_api_3_0/core/httpx_transport.py +766 -0
  45. swagger_petstore_open_api_3_0/core/models.py +143 -0
  46. swagger_petstore_open_api_3_0/core/optionality.py +130 -0
  47. swagger_petstore_open_api_3_0/core/params.py +161 -0
  48. swagger_petstore_open_api_3_0/core/raw_client.py +388 -0
  49. swagger_petstore_open_api_3_0/core/request_options.py +94 -0
  50. swagger_petstore_open_api_3_0/core/results.py +110 -0
  51. swagger_petstore_open_api_3_0/core/runtime_env.py +43 -0
  52. swagger_petstore_open_api_3_0/core/servers.py +33 -0
  53. swagger_petstore_open_api_3_0/core/transport.py +248 -0
  54. swagger_petstore_open_api_3_0/errors/__init__.py +48 -0
  55. swagger_petstore_open_api_3_0/errors/add_pet_error.py +21 -0
  56. swagger_petstore_open_api_3_0/errors/delete_order_error.py +21 -0
  57. swagger_petstore_open_api_3_0/errors/delete_pet_error.py +21 -0
  58. swagger_petstore_open_api_3_0/errors/delete_user_error.py +21 -0
  59. swagger_petstore_open_api_3_0/errors/find_pets_by_status_error.py +21 -0
  60. swagger_petstore_open_api_3_0/errors/find_pets_by_tags_error.py +21 -0
  61. swagger_petstore_open_api_3_0/errors/get_order_by_id_error.py +21 -0
  62. swagger_petstore_open_api_3_0/errors/get_pet_by_id_error.py +21 -0
  63. swagger_petstore_open_api_3_0/errors/get_user_by_name_error.py +21 -0
  64. swagger_petstore_open_api_3_0/errors/login_user_error.py +21 -0
  65. swagger_petstore_open_api_3_0/errors/place_order_error.py +21 -0
  66. swagger_petstore_open_api_3_0/errors/update_pet_error.py +21 -0
  67. swagger_petstore_open_api_3_0/errors/update_pet_with_form_error.py +21 -0
  68. swagger_petstore_open_api_3_0/errors/update_user_error.py +21 -0
  69. swagger_petstore_open_api_3_0/errors/upload_file_error.py +21 -0
  70. swagger_petstore_open_api_3_0/models/__init__.py +23 -0
  71. swagger_petstore_open_api_3_0/models/api_response.py +18 -0
  72. swagger_petstore_open_api_3_0/models/category.py +15 -0
  73. swagger_petstore_open_api_3_0/models/enums/__init__.py +4 -0
  74. swagger_petstore_open_api_3_0/models/enums/order_status.py +17 -0
  75. swagger_petstore_open_api_3_0/models/enums/pet_status.py +17 -0
  76. swagger_petstore_open_api_3_0/models/order.py +27 -0
  77. swagger_petstore_open_api_3_0/models/pet.py +28 -0
  78. swagger_petstore_open_api_3_0/models/tag.py +15 -0
  79. swagger_petstore_open_api_3_0/models/user.py +29 -0
  80. swagger_petstore_open_api_3_0/py.typed +0 -0
  81. swagger_petstore_open_api_3_0/server/__init__.py +21 -0
  82. swagger_petstore_open_api_3_0/server/server.py +17 -0
  83. 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