openapi-python-client 0.29.0__py3-none-any.whl → 0.30.0__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.
- openapi_python_client/__init__.py +30 -21
- openapi_python_client/cli.py +10 -3
- openapi_python_client/config.py +4 -1
- openapi_python_client/parser/bodies.py +8 -7
- openapi_python_client/parser/openapi.py +58 -48
- openapi_python_client/parser/properties/__init__.py +36 -33
- openapi_python_client/parser/properties/any.py +12 -10
- openapi_python_client/parser/properties/boolean.py +14 -13
- openapi_python_client/parser/properties/const.py +11 -10
- openapi_python_client/parser/properties/date.py +13 -11
- openapi_python_client/parser/properties/datetime.py +13 -11
- openapi_python_client/parser/properties/enum_property.py +23 -20
- openapi_python_client/parser/properties/file.py +12 -10
- openapi_python_client/parser/properties/float.py +14 -13
- openapi_python_client/parser/properties/int.py +12 -11
- openapi_python_client/parser/properties/list_property.py +22 -22
- openapi_python_client/parser/properties/literal_enum_property.py +20 -20
- openapi_python_client/parser/properties/merge_properties.py +9 -6
- openapi_python_client/parser/properties/model_property.py +35 -34
- openapi_python_client/parser/properties/none.py +12 -11
- openapi_python_client/parser/properties/protocol.py +42 -32
- openapi_python_client/parser/properties/schemas.py +30 -23
- openapi_python_client/parser/properties/string.py +11 -11
- openapi_python_client/parser/properties/union.py +24 -22
- openapi_python_client/parser/properties/uuid.py +12 -11
- openapi_python_client/parser/responses.py +31 -24
- openapi_python_client/schema/__init__.py +2 -1
- openapi_python_client/schema/openapi_schema_pydantic/callback.py +3 -1
- openapi_python_client/schema/openapi_schema_pydantic/components.py +10 -9
- openapi_python_client/schema/openapi_schema_pydantic/contact.py +5 -3
- openapi_python_client/schema/openapi_schema_pydantic/discriminator.py +4 -2
- openapi_python_client/schema/openapi_schema_pydantic/encoding.py +4 -3
- openapi_python_client/schema/openapi_schema_pydantic/example.py +5 -3
- openapi_python_client/schema/openapi_schema_pydantic/external_documentation.py +4 -2
- openapi_python_client/schema/openapi_schema_pydantic/header.py +20 -6
- openapi_python_client/schema/openapi_schema_pydantic/info.py +5 -4
- openapi_python_client/schema/openapi_schema_pydantic/license.py +4 -2
- openapi_python_client/schema/openapi_schema_pydantic/link.py +5 -4
- openapi_python_client/schema/openapi_schema_pydantic/media_type.py +3 -2
- openapi_python_client/schema/openapi_schema_pydantic/oauth_flow.py +6 -4
- openapi_python_client/schema/openapi_schema_pydantic/open_api.py +5 -3
- openapi_python_client/schema/openapi_schema_pydantic/operation.py +6 -5
- openapi_python_client/schema/openapi_schema_pydantic/parameter.py +6 -5
- openapi_python_client/schema/openapi_schema_pydantic/path_item.py +5 -3
- openapi_python_client/schema/openapi_schema_pydantic/paths.py +2 -1
- openapi_python_client/schema/openapi_schema_pydantic/reference.py +3 -1
- openapi_python_client/schema/openapi_schema_pydantic/request_body.py +3 -2
- openapi_python_client/schema/openapi_schema_pydantic/response.py +5 -4
- openapi_python_client/schema/openapi_schema_pydantic/responses.py +2 -1
- openapi_python_client/schema/openapi_schema_pydantic/schema.py +9 -8
- openapi_python_client/schema/openapi_schema_pydantic/security_requirement.py +3 -1
- openapi_python_client/schema/openapi_schema_pydantic/security_scheme.py +8 -7
- openapi_python_client/schema/openapi_schema_pydantic/server.py +4 -3
- openapi_python_client/schema/openapi_schema_pydantic/server_variable.py +5 -3
- openapi_python_client/schema/openapi_schema_pydantic/tag.py +3 -2
- openapi_python_client/schema/openapi_schema_pydantic/xml.py +5 -3
- openapi_python_client/schema/ref.py +52 -0
- openapi_python_client/schema/untrusted_string.py +56 -0
- openapi_python_client/strings.py +245 -0
- openapi_python_client/templates/README.md.jinja +9 -9
- openapi_python_client/templates/client.py.jinja +31 -31
- openapi_python_client/templates/endpoint_macros.py.jinja +19 -19
- openapi_python_client/templates/endpoint_module.py.jinja +18 -21
- openapi_python_client/templates/helpers.jinja +3 -7
- openapi_python_client/templates/literal_enum.py.jinja +1 -1
- openapi_python_client/templates/model.py.jinja +18 -18
- openapi_python_client/templates/package_init.py.jinja +2 -2
- openapi_python_client/templates/property_templates/const_property.py.jinja +3 -3
- openapi_python_client/templates/property_templates/date_property.py.jinja +1 -1
- openapi_python_client/templates/property_templates/datetime_property.py.jinja +1 -1
- openapi_python_client/templates/property_templates/enum_property.py.jinja +1 -1
- openapi_python_client/templates/property_templates/file_property.py.jinja +1 -1
- openapi_python_client/templates/property_templates/list_property.py.jinja +3 -3
- openapi_python_client/templates/property_templates/literal_enum_property.py.jinja +2 -2
- openapi_python_client/templates/property_templates/model_property.py.jinja +1 -1
- openapi_python_client/templates/property_templates/property_macros.py.jinja +1 -1
- openapi_python_client/templates/property_templates/union_property.py.jinja +9 -9
- openapi_python_client/templates/property_templates/uuid_property.py.jinja +1 -1
- openapi_python_client/templates/pyproject_pdm.toml.jinja +3 -3
- openapi_python_client/templates/pyproject_poetry.toml.jinja +3 -3
- openapi_python_client/templates/pyproject_uv.toml.jinja +4 -4
- openapi_python_client/templates/setup.py.jinja +3 -3
- openapi_python_client/templates/str_enum.py.jinja +2 -2
- openapi_python_client/templates/types.py.jinja +2 -2
- {openapi_python_client-0.29.0.dist-info → openapi_python_client-0.30.0.dist-info}/METADATA +10 -9
- openapi_python_client-0.30.0.dist-info/RECORD +115 -0
- {openapi_python_client-0.29.0.dist-info → openapi_python_client-0.30.0.dist-info}/WHEEL +1 -1
- openapi_python_client/utils.py +0 -122
- openapi_python_client-0.29.0.dist-info/RECORD +0 -113
- {openapi_python_client-0.29.0.dist-info → openapi_python_client-0.30.0.dist-info}/entry_points.txt +0 -0
- {openapi_python_client-0.29.0.dist-info → openapi_python_client-0.30.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -18,8 +18,10 @@ from collections.abc import Iterable
|
|
|
18
18
|
|
|
19
19
|
from attrs import evolve
|
|
20
20
|
|
|
21
|
-
from ... import Config,
|
|
21
|
+
from ... import Config, strings
|
|
22
22
|
from ... import schema as oai
|
|
23
|
+
from ...schema.ref import Ref
|
|
24
|
+
from ...schema.untrusted_string import UntrustedString
|
|
23
25
|
from ..errors import ParameterError, ParseError, PropertyError
|
|
24
26
|
from .any import AnyProperty
|
|
25
27
|
from .boolean import BooleanProperty
|
|
@@ -51,11 +53,11 @@ from .uuid import UuidProperty
|
|
|
51
53
|
|
|
52
54
|
|
|
53
55
|
def _string_based_property(
|
|
54
|
-
name:
|
|
56
|
+
name: UntrustedString, required: bool, data: oai.Schema, config: Config
|
|
55
57
|
) -> StringProperty | DateProperty | DateTimeProperty | FileProperty | UuidProperty | PropertyError:
|
|
56
58
|
"""Construct a Property from the type "string" """
|
|
57
59
|
string_format = data.schema_format
|
|
58
|
-
python_name =
|
|
60
|
+
python_name = strings.PythonIdentifier(value=name, prefix=config.field_prefix)
|
|
59
61
|
if string_format == "date-time":
|
|
60
62
|
return DateTimeProperty.build(
|
|
61
63
|
name=name,
|
|
@@ -103,16 +105,17 @@ def _string_based_property(
|
|
|
103
105
|
|
|
104
106
|
|
|
105
107
|
def _property_from_ref(
|
|
106
|
-
|
|
108
|
+
*,
|
|
109
|
+
name: UntrustedString,
|
|
107
110
|
required: bool,
|
|
108
111
|
parent: oai.Schema | None,
|
|
109
112
|
data: oai.Reference,
|
|
110
113
|
schemas: Schemas,
|
|
111
114
|
config: Config,
|
|
112
|
-
roots: set[ReferencePath |
|
|
115
|
+
roots: set[ReferencePath | strings.ClassName],
|
|
113
116
|
) -> tuple[Property | PropertyError, Schemas]:
|
|
114
117
|
ref_path = parse_reference_path(data.ref)
|
|
115
|
-
if isinstance(ref_path, ParseError):
|
|
118
|
+
if isinstance(ref_path, ParseError): # pragma: no cover
|
|
116
119
|
return PropertyError(data=data, detail=ref_path.detail), schemas
|
|
117
120
|
existing = schemas.classes_by_reference.get(ref_path)
|
|
118
121
|
if not existing:
|
|
@@ -130,7 +133,7 @@ def _property_from_ref(
|
|
|
130
133
|
existing,
|
|
131
134
|
required=required,
|
|
132
135
|
name=name,
|
|
133
|
-
python_name=
|
|
136
|
+
python_name=strings.PythonIdentifier(value=name, prefix=config.field_prefix),
|
|
134
137
|
default=default, # type: ignore # mypy can't tell that default comes from the same class...
|
|
135
138
|
)
|
|
136
139
|
|
|
@@ -139,18 +142,18 @@ def _property_from_ref(
|
|
|
139
142
|
|
|
140
143
|
|
|
141
144
|
def property_from_data( # noqa: PLR0911, PLR0912
|
|
142
|
-
|
|
145
|
+
*,
|
|
146
|
+
name: UntrustedString,
|
|
143
147
|
required: bool,
|
|
144
148
|
data: oai.Reference | oai.Schema,
|
|
145
149
|
schemas: Schemas,
|
|
146
150
|
parent_name: str,
|
|
147
151
|
config: Config,
|
|
148
152
|
process_properties: bool = True,
|
|
149
|
-
roots: set[ReferencePath |
|
|
153
|
+
roots: set[ReferencePath | strings.ClassName] | None = None,
|
|
150
154
|
) -> tuple[Property | PropertyError, Schemas]:
|
|
151
155
|
"""Generate a Property from the OpenAPI dictionary representation of it"""
|
|
152
156
|
roots = roots or set()
|
|
153
|
-
name = utils.remove_string_escapes(name)
|
|
154
157
|
if isinstance(data, oai.Reference):
|
|
155
158
|
return _property_from_ref(
|
|
156
159
|
name=name,
|
|
@@ -190,7 +193,7 @@ def property_from_data( # noqa: PLR0911, PLR0912
|
|
|
190
193
|
name=name,
|
|
191
194
|
required=required,
|
|
192
195
|
default=data.default,
|
|
193
|
-
python_name=
|
|
196
|
+
python_name=strings.PythonIdentifier(value=name, prefix=config.field_prefix),
|
|
194
197
|
description=data.description,
|
|
195
198
|
example=data.example,
|
|
196
199
|
),
|
|
@@ -230,7 +233,7 @@ def property_from_data( # noqa: PLR0911, PLR0912
|
|
|
230
233
|
required=required,
|
|
231
234
|
default=data.default,
|
|
232
235
|
const=data.const,
|
|
233
|
-
python_name=
|
|
236
|
+
python_name=strings.PythonIdentifier(value=name, prefix=config.field_prefix),
|
|
234
237
|
description=data.description,
|
|
235
238
|
),
|
|
236
239
|
schemas,
|
|
@@ -246,7 +249,7 @@ def property_from_data( # noqa: PLR0911, PLR0912
|
|
|
246
249
|
name=name,
|
|
247
250
|
default=data.default,
|
|
248
251
|
required=required,
|
|
249
|
-
python_name=
|
|
252
|
+
python_name=strings.PythonIdentifier(value=name, prefix=config.field_prefix),
|
|
250
253
|
description=data.description,
|
|
251
254
|
example=data.example,
|
|
252
255
|
),
|
|
@@ -258,7 +261,7 @@ def property_from_data( # noqa: PLR0911, PLR0912
|
|
|
258
261
|
name=name,
|
|
259
262
|
default=data.default,
|
|
260
263
|
required=required,
|
|
261
|
-
python_name=
|
|
264
|
+
python_name=strings.PythonIdentifier(value=name, prefix=config.field_prefix),
|
|
262
265
|
description=data.description,
|
|
263
266
|
example=data.example,
|
|
264
267
|
),
|
|
@@ -270,7 +273,7 @@ def property_from_data( # noqa: PLR0911, PLR0912
|
|
|
270
273
|
name=name,
|
|
271
274
|
required=required,
|
|
272
275
|
default=None,
|
|
273
|
-
python_name=
|
|
276
|
+
python_name=strings.PythonIdentifier(value=name, prefix=config.field_prefix),
|
|
274
277
|
description=data.description,
|
|
275
278
|
example=data.example,
|
|
276
279
|
),
|
|
@@ -303,7 +306,7 @@ def property_from_data( # noqa: PLR0911, PLR0912
|
|
|
303
306
|
name=name,
|
|
304
307
|
required=required,
|
|
305
308
|
default=data.default,
|
|
306
|
-
python_name=
|
|
309
|
+
python_name=strings.PythonIdentifier(value=name, prefix=config.field_prefix),
|
|
307
310
|
description=data.description,
|
|
308
311
|
example=data.example,
|
|
309
312
|
),
|
|
@@ -313,11 +316,11 @@ def property_from_data( # noqa: PLR0911, PLR0912
|
|
|
313
316
|
|
|
314
317
|
def _create_schemas(
|
|
315
318
|
*,
|
|
316
|
-
components: dict[
|
|
319
|
+
components: dict[UntrustedString, oai.Reference | oai.Schema],
|
|
317
320
|
schemas: Schemas,
|
|
318
321
|
config: Config,
|
|
319
322
|
) -> Schemas:
|
|
320
|
-
to_process: Iterable[tuple[
|
|
323
|
+
to_process: Iterable[tuple[UntrustedString, oai.Reference | oai.Schema]] = components.items()
|
|
321
324
|
still_making_progress = True
|
|
322
325
|
errors: list[PropertyError] = []
|
|
323
326
|
|
|
@@ -325,12 +328,12 @@ def _create_schemas(
|
|
|
325
328
|
while still_making_progress:
|
|
326
329
|
still_making_progress = False
|
|
327
330
|
errors = []
|
|
328
|
-
next_round: list[tuple[
|
|
331
|
+
next_round: list[tuple[UntrustedString, oai.Reference | oai.Schema]] = []
|
|
329
332
|
# Only accumulate errors from the last round, since we might fix some along the way
|
|
330
333
|
for name, data in to_process:
|
|
331
334
|
schema_data: oai.Reference | oai.Schema | None = data
|
|
332
|
-
ref_path = parse_reference_path(f"#/components/schemas/{name}")
|
|
333
|
-
if isinstance(ref_path, ParseError):
|
|
335
|
+
ref_path = parse_reference_path(Ref(f"#/components/schemas/{name.get_untrusted_value()}"))
|
|
336
|
+
if isinstance(ref_path, ParseError): # pragma: no cover
|
|
334
337
|
schemas.errors.append(PropertyError(detail=ref_path.detail, data=data))
|
|
335
338
|
continue
|
|
336
339
|
if isinstance(data, oai.Reference):
|
|
@@ -361,13 +364,13 @@ def _create_schemas(
|
|
|
361
364
|
return schemas
|
|
362
365
|
|
|
363
366
|
|
|
364
|
-
def _propogate_removal(*, root: ReferencePath |
|
|
365
|
-
if isinstance(root,
|
|
367
|
+
def _propogate_removal(*, root: ReferencePath | strings.ClassName, schemas: Schemas, error: PropertyError) -> None:
|
|
368
|
+
if isinstance(root, strings.ClassName):
|
|
366
369
|
schemas.classes_by_name.pop(root, None)
|
|
367
370
|
return
|
|
368
371
|
if root in schemas.classes_by_reference:
|
|
369
372
|
error.detail = error.detail or ""
|
|
370
|
-
error.detail += f"\n{root}"
|
|
373
|
+
error.detail += f"\n{root.get_untrusted_value()}"
|
|
371
374
|
del schemas.classes_by_reference[root]
|
|
372
375
|
for child in schemas.dependencies.get(root, set()):
|
|
373
376
|
_propogate_removal(root=child, schemas=schemas, error=error)
|
|
@@ -399,10 +402,10 @@ def _process_models(*, schemas: Schemas, config: Config) -> Schemas:
|
|
|
399
402
|
for model_prop in to_process:
|
|
400
403
|
schemas_or_err = process_model(model_prop, schemas=schemas, config=config)
|
|
401
404
|
if isinstance(schemas_or_err, PropertyError):
|
|
402
|
-
schemas_or_err.header = f"\nUnable to process schema {model_prop.name}:"
|
|
405
|
+
schemas_or_err.header = f"\nUnable to process schema {model_prop.name.get_untrusted_value()}:"
|
|
403
406
|
if isinstance(schemas_or_err.data, oai.Reference) and schemas_or_err.data.ref.endswith(
|
|
404
407
|
f"/{model_prop.class_info.name}"
|
|
405
|
-
):
|
|
408
|
+
): # pragma: no cover
|
|
406
409
|
schemas_or_err.detail = schemas_or_err.detail or ""
|
|
407
410
|
schemas_or_err.detail += "\n\nRecursive allOf reference found"
|
|
408
411
|
final_model_errors.append((model_prop, schemas_or_err))
|
|
@@ -421,7 +424,7 @@ def _process_models(*, schemas: Schemas, config: Config) -> Schemas:
|
|
|
421
424
|
|
|
422
425
|
def build_schemas(
|
|
423
426
|
*,
|
|
424
|
-
components: dict[
|
|
427
|
+
components: dict[UntrustedString, oai.Reference | oai.Schema],
|
|
425
428
|
schemas: Schemas,
|
|
426
429
|
config: Config,
|
|
427
430
|
) -> Schemas:
|
|
@@ -433,12 +436,12 @@ def build_schemas(
|
|
|
433
436
|
|
|
434
437
|
def build_parameters(
|
|
435
438
|
*,
|
|
436
|
-
components: dict[
|
|
439
|
+
components: dict[UntrustedString, oai.Reference | oai.Parameter],
|
|
437
440
|
parameters: Parameters,
|
|
438
441
|
config: Config,
|
|
439
442
|
) -> Parameters:
|
|
440
443
|
"""Get a list of Parameters from an OpenAPI dict"""
|
|
441
|
-
to_process: Iterable[tuple[
|
|
444
|
+
to_process: Iterable[tuple[UntrustedString, oai.Reference | oai.Parameter]] = []
|
|
442
445
|
if components is not None:
|
|
443
446
|
to_process = components.items()
|
|
444
447
|
still_making_progress = True
|
|
@@ -451,17 +454,17 @@ def build_parameters(
|
|
|
451
454
|
next_round = []
|
|
452
455
|
# Only accumulate errors from the last round, since we might fix some along the way
|
|
453
456
|
for name, data in to_process:
|
|
454
|
-
if isinstance(data, oai.Reference):
|
|
457
|
+
if isinstance(data, oai.Reference): # pragma: no cover
|
|
455
458
|
parameters.errors.append(ParameterError(data=data, detail="Reference parameters are not supported."))
|
|
456
459
|
continue
|
|
457
|
-
ref_path = parse_reference_path(f"#/components/parameters/{name}")
|
|
458
|
-
if isinstance(ref_path, ParseError):
|
|
460
|
+
ref_path = parse_reference_path(Ref(f"#/components/parameters/{name.get_untrusted_value()}"))
|
|
461
|
+
if isinstance(ref_path, ParseError): # pragma: no cover
|
|
459
462
|
parameters.errors.append(ParameterError(detail=ref_path.detail, data=data))
|
|
460
463
|
continue
|
|
461
464
|
parameters_or_err = update_parameters_with_data(
|
|
462
465
|
ref_path=ref_path, data=data, parameters=parameters, config=config
|
|
463
466
|
)
|
|
464
|
-
if isinstance(parameters_or_err, ParameterError):
|
|
467
|
+
if isinstance(parameters_or_err, ParameterError): # pragma: no cover
|
|
465
468
|
next_round.append((name, data))
|
|
466
469
|
errors.append(parameters_or_err)
|
|
467
470
|
continue
|
|
@@ -2,10 +2,11 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from typing import Any, ClassVar
|
|
4
4
|
|
|
5
|
-
from attr import define
|
|
5
|
+
from attr import define, field
|
|
6
6
|
|
|
7
|
-
from ...
|
|
8
|
-
from
|
|
7
|
+
from ...schema.untrusted_string import UntrustedString
|
|
8
|
+
from ...strings import PythonCode, PythonIdentifier
|
|
9
|
+
from .protocol import PropertyProtocol, Value, convert_example
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
@define
|
|
@@ -15,12 +16,13 @@ class AnyProperty(PropertyProtocol):
|
|
|
15
16
|
@classmethod
|
|
16
17
|
def build(
|
|
17
18
|
cls,
|
|
18
|
-
|
|
19
|
+
*,
|
|
20
|
+
name: UntrustedString,
|
|
19
21
|
required: bool,
|
|
20
22
|
default: Any,
|
|
21
23
|
python_name: PythonIdentifier,
|
|
22
|
-
description:
|
|
23
|
-
example:
|
|
24
|
+
description: UntrustedString | None,
|
|
25
|
+
example: Any,
|
|
24
26
|
) -> AnyProperty:
|
|
25
27
|
return cls(
|
|
26
28
|
name=name,
|
|
@@ -39,13 +41,13 @@ class AnyProperty(PropertyProtocol):
|
|
|
39
41
|
return value
|
|
40
42
|
if isinstance(value, str):
|
|
41
43
|
return StringProperty.convert_value(value)
|
|
42
|
-
return Value(python_code=str(value), raw_value=value)
|
|
44
|
+
return Value(python_code=PythonCode(str(value)), raw_value=value)
|
|
43
45
|
|
|
44
|
-
name:
|
|
46
|
+
name: UntrustedString
|
|
45
47
|
required: bool
|
|
46
48
|
default: Value | None
|
|
47
49
|
python_name: PythonIdentifier
|
|
48
|
-
description:
|
|
49
|
-
example:
|
|
50
|
+
description: UntrustedString | None
|
|
51
|
+
example: UntrustedString | None = field(converter=convert_example)
|
|
50
52
|
_type_string: ClassVar[str] = "Any"
|
|
51
53
|
_json_type_string: ClassVar[str] = "Any"
|
|
@@ -2,24 +2,24 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from typing import Any, ClassVar
|
|
4
4
|
|
|
5
|
-
from attr import define
|
|
5
|
+
from attr import define, field
|
|
6
6
|
|
|
7
7
|
from ... import schema as oai
|
|
8
|
-
from ...
|
|
8
|
+
from ...strings import PythonCode, PythonIdentifier
|
|
9
9
|
from ..errors import PropertyError
|
|
10
|
-
from .protocol import PropertyProtocol, Value
|
|
10
|
+
from .protocol import PropertyProtocol, Value, convert_example
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
@define
|
|
14
14
|
class BooleanProperty(PropertyProtocol):
|
|
15
15
|
"""Property for bool"""
|
|
16
16
|
|
|
17
|
-
name:
|
|
17
|
+
name: oai.UntrustedString
|
|
18
18
|
required: bool
|
|
19
19
|
default: Value | None
|
|
20
20
|
python_name: PythonIdentifier
|
|
21
|
-
description:
|
|
22
|
-
example:
|
|
21
|
+
description: oai.UntrustedString | None
|
|
22
|
+
example: oai.UntrustedString | None = field(converter=convert_example)
|
|
23
23
|
|
|
24
24
|
_type_string: ClassVar[str] = "bool"
|
|
25
25
|
_json_type_string: ClassVar[str] = "bool"
|
|
@@ -34,12 +34,13 @@ class BooleanProperty(PropertyProtocol):
|
|
|
34
34
|
@classmethod
|
|
35
35
|
def build(
|
|
36
36
|
cls,
|
|
37
|
-
|
|
37
|
+
*,
|
|
38
|
+
name: oai.UntrustedString,
|
|
38
39
|
required: bool,
|
|
39
40
|
default: Any,
|
|
40
41
|
python_name: PythonIdentifier,
|
|
41
|
-
description:
|
|
42
|
-
example:
|
|
42
|
+
description: oai.UntrustedString | None,
|
|
43
|
+
example: Any,
|
|
43
44
|
) -> BooleanProperty | PropertyError:
|
|
44
45
|
checked_default = cls.convert_value(default)
|
|
45
46
|
if isinstance(checked_default, PropertyError):
|
|
@@ -54,14 +55,14 @@ class BooleanProperty(PropertyProtocol):
|
|
|
54
55
|
)
|
|
55
56
|
|
|
56
57
|
@classmethod
|
|
57
|
-
def convert_value(cls, value: Any) -> Value |
|
|
58
|
+
def convert_value(cls, value: Any) -> Value | PropertyError | None:
|
|
58
59
|
if isinstance(value, Value) or value is None:
|
|
59
60
|
return value
|
|
60
61
|
if isinstance(value, str):
|
|
61
62
|
if value.lower() == "true":
|
|
62
|
-
return Value(python_code="True", raw_value=value)
|
|
63
|
+
return Value(python_code=PythonCode("True"), raw_value=value)
|
|
63
64
|
elif value.lower() == "false":
|
|
64
|
-
return Value(python_code="False", raw_value=value)
|
|
65
|
+
return Value(python_code=PythonCode("False"), raw_value=value)
|
|
65
66
|
if isinstance(value, bool):
|
|
66
|
-
return Value(python_code=str(value), raw_value=value)
|
|
67
|
+
return Value(python_code=PythonCode(str(value)), raw_value=value)
|
|
67
68
|
return PropertyError(f"Invalid boolean value: {value}")
|
|
@@ -4,7 +4,8 @@ from typing import Any, ClassVar, overload
|
|
|
4
4
|
|
|
5
5
|
from attr import define
|
|
6
6
|
|
|
7
|
-
from ...
|
|
7
|
+
from ... import schema as oai
|
|
8
|
+
from ...strings import PythonCode, PythonIdentifier
|
|
8
9
|
from ..errors import PropertyError
|
|
9
10
|
from .protocol import PropertyProtocol, Value
|
|
10
11
|
from .string import StringProperty
|
|
@@ -14,12 +15,12 @@ from .string import StringProperty
|
|
|
14
15
|
class ConstProperty(PropertyProtocol):
|
|
15
16
|
"""A property representing a const value"""
|
|
16
17
|
|
|
17
|
-
name:
|
|
18
|
+
name: oai.UntrustedString
|
|
18
19
|
required: bool
|
|
19
20
|
value: Value
|
|
20
21
|
default: Value | None
|
|
21
22
|
python_name: PythonIdentifier
|
|
22
|
-
description:
|
|
23
|
+
description: oai.UntrustedString | None
|
|
23
24
|
example: None
|
|
24
25
|
template: ClassVar[str] = "const_property.py.jinja"
|
|
25
26
|
|
|
@@ -29,10 +30,10 @@ class ConstProperty(PropertyProtocol):
|
|
|
29
30
|
*,
|
|
30
31
|
const: str | int | float | bool,
|
|
31
32
|
default: Any,
|
|
32
|
-
name:
|
|
33
|
+
name: oai.UntrustedString,
|
|
33
34
|
python_name: PythonIdentifier,
|
|
34
35
|
required: bool,
|
|
35
|
-
description:
|
|
36
|
+
description: oai.UntrustedString | None,
|
|
36
37
|
) -> ConstProperty | PropertyError:
|
|
37
38
|
"""
|
|
38
39
|
Create a `ConstProperty` the right way.
|
|
@@ -62,7 +63,7 @@ class ConstProperty(PropertyProtocol):
|
|
|
62
63
|
prop.default = converted_default
|
|
63
64
|
return prop
|
|
64
65
|
|
|
65
|
-
def convert_value(self, value: Any) -> Value |
|
|
66
|
+
def convert_value(self, value: Any) -> Value | PropertyError | None:
|
|
66
67
|
value = self._convert_value(value)
|
|
67
68
|
if value is None:
|
|
68
69
|
return value
|
|
@@ -87,16 +88,16 @@ class ConstProperty(PropertyProtocol):
|
|
|
87
88
|
return value
|
|
88
89
|
if isinstance(value, str):
|
|
89
90
|
return StringProperty.convert_value(value)
|
|
90
|
-
return Value(python_code=str(value), raw_value=value)
|
|
91
|
+
return Value(python_code=PythonCode(str(value)), raw_value=value)
|
|
91
92
|
|
|
92
93
|
def get_type_string(
|
|
93
94
|
self,
|
|
94
95
|
no_optional: bool = False,
|
|
95
96
|
json: bool = False,
|
|
96
|
-
) ->
|
|
97
|
-
lit = f"Literal[{self.value.python_code}]"
|
|
97
|
+
) -> PythonCode:
|
|
98
|
+
lit = PythonCode(f"Literal[{self.value.python_code.as_unembedded_code()}]")
|
|
98
99
|
if not no_optional and not self.required:
|
|
99
|
-
return f"{lit} | Unset"
|
|
100
|
+
return PythonCode(f"{lit.as_unembedded_code()} | Unset")
|
|
100
101
|
return lit
|
|
101
102
|
|
|
102
103
|
def get_imports(self, *, prefix: str) -> set[str]:
|
|
@@ -3,23 +3,24 @@ from __future__ import annotations
|
|
|
3
3
|
import datetime
|
|
4
4
|
from typing import Any, ClassVar
|
|
5
5
|
|
|
6
|
-
from attr import define
|
|
6
|
+
from attr import define, field
|
|
7
7
|
|
|
8
|
-
from ...
|
|
8
|
+
from ... import schema as oai
|
|
9
|
+
from ...strings import PythonCode, PythonIdentifier
|
|
9
10
|
from ..errors import PropertyError
|
|
10
|
-
from .protocol import PropertyProtocol, Value
|
|
11
|
+
from .protocol import PropertyProtocol, Value, convert_example
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
@define
|
|
14
15
|
class DateProperty(PropertyProtocol):
|
|
15
16
|
"""A property of type datetime.date"""
|
|
16
17
|
|
|
17
|
-
name:
|
|
18
|
+
name: oai.UntrustedString
|
|
18
19
|
required: bool
|
|
19
20
|
default: Value | None
|
|
20
21
|
python_name: PythonIdentifier
|
|
21
|
-
description:
|
|
22
|
-
example:
|
|
22
|
+
description: oai.UntrustedString | None
|
|
23
|
+
example: oai.UntrustedString | None = field(converter=convert_example)
|
|
23
24
|
|
|
24
25
|
_type_string: ClassVar[str] = "datetime.date"
|
|
25
26
|
_json_type_string: ClassVar[str] = "str"
|
|
@@ -28,12 +29,13 @@ class DateProperty(PropertyProtocol):
|
|
|
28
29
|
@classmethod
|
|
29
30
|
def build(
|
|
30
31
|
cls,
|
|
31
|
-
|
|
32
|
+
*,
|
|
33
|
+
name: oai.UntrustedString,
|
|
32
34
|
required: bool,
|
|
33
35
|
default: Any,
|
|
34
36
|
python_name: PythonIdentifier,
|
|
35
|
-
description:
|
|
36
|
-
example:
|
|
37
|
+
description: oai.UntrustedString | None,
|
|
38
|
+
example: Any,
|
|
37
39
|
) -> DateProperty | PropertyError:
|
|
38
40
|
checked_default = cls.convert_value(default)
|
|
39
41
|
if isinstance(checked_default, PropertyError):
|
|
@@ -49,7 +51,7 @@ class DateProperty(PropertyProtocol):
|
|
|
49
51
|
)
|
|
50
52
|
|
|
51
53
|
@classmethod
|
|
52
|
-
def convert_value(cls, value: Any) -> Value |
|
|
54
|
+
def convert_value(cls, value: Any) -> Value | PropertyError | None:
|
|
53
55
|
if isinstance(value, Value) or value is None:
|
|
54
56
|
return value
|
|
55
57
|
if isinstance(value, str):
|
|
@@ -57,7 +59,7 @@ class DateProperty(PropertyProtocol):
|
|
|
57
59
|
datetime.date.fromisoformat(value) # make sure it's a valid value
|
|
58
60
|
except ValueError as e:
|
|
59
61
|
return PropertyError(f"Invalid date: {e}")
|
|
60
|
-
return Value(python_code=f"datetime.date.fromisoformat({value!r})", raw_value=value)
|
|
62
|
+
return Value(python_code=PythonCode(f"datetime.date.fromisoformat({value!r})"), raw_value=value)
|
|
61
63
|
return PropertyError(f"Cannot convert {value} to a date")
|
|
62
64
|
|
|
63
65
|
def get_imports(self, *, prefix: str) -> set[str]:
|
|
@@ -3,11 +3,12 @@ from __future__ import annotations
|
|
|
3
3
|
import datetime
|
|
4
4
|
from typing import Any, ClassVar
|
|
5
5
|
|
|
6
|
-
from attr import define
|
|
6
|
+
from attr import define, field
|
|
7
7
|
|
|
8
|
-
from ...
|
|
8
|
+
from ... import schema as oai
|
|
9
|
+
from ...strings import PythonCode, PythonIdentifier
|
|
9
10
|
from ..errors import PropertyError
|
|
10
|
-
from .protocol import PropertyProtocol, Value
|
|
11
|
+
from .protocol import PropertyProtocol, Value, convert_example
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
@define
|
|
@@ -16,12 +17,12 @@ class DateTimeProperty(PropertyProtocol):
|
|
|
16
17
|
A property of type datetime.datetime
|
|
17
18
|
"""
|
|
18
19
|
|
|
19
|
-
name:
|
|
20
|
+
name: oai.UntrustedString
|
|
20
21
|
required: bool
|
|
21
22
|
default: Value | None
|
|
22
23
|
python_name: PythonIdentifier
|
|
23
|
-
description:
|
|
24
|
-
example:
|
|
24
|
+
description: oai.UntrustedString | None
|
|
25
|
+
example: oai.UntrustedString | None = field(converter=convert_example)
|
|
25
26
|
|
|
26
27
|
_type_string: ClassVar[str] = "datetime.datetime"
|
|
27
28
|
_json_type_string: ClassVar[str] = "str"
|
|
@@ -30,12 +31,13 @@ class DateTimeProperty(PropertyProtocol):
|
|
|
30
31
|
@classmethod
|
|
31
32
|
def build(
|
|
32
33
|
cls,
|
|
33
|
-
|
|
34
|
+
*,
|
|
35
|
+
name: oai.UntrustedString,
|
|
34
36
|
required: bool,
|
|
35
37
|
default: Any,
|
|
36
38
|
python_name: PythonIdentifier,
|
|
37
|
-
description:
|
|
38
|
-
example:
|
|
39
|
+
description: oai.UntrustedString | None,
|
|
40
|
+
example: Any,
|
|
39
41
|
) -> DateTimeProperty | PropertyError:
|
|
40
42
|
checked_default = cls.convert_value(default)
|
|
41
43
|
if isinstance(checked_default, PropertyError):
|
|
@@ -51,7 +53,7 @@ class DateTimeProperty(PropertyProtocol):
|
|
|
51
53
|
)
|
|
52
54
|
|
|
53
55
|
@classmethod
|
|
54
|
-
def convert_value(cls, value: Any) -> Value |
|
|
56
|
+
def convert_value(cls, value: Any) -> Value | PropertyError | None:
|
|
55
57
|
if value is None or isinstance(value, Value):
|
|
56
58
|
return value
|
|
57
59
|
if isinstance(value, str):
|
|
@@ -59,7 +61,7 @@ class DateTimeProperty(PropertyProtocol):
|
|
|
59
61
|
datetime.datetime.fromisoformat(value) # make sure it's a valid value
|
|
60
62
|
except ValueError as e:
|
|
61
63
|
return PropertyError(f"Invalid datetime: {e}")
|
|
62
|
-
return Value(python_code=f"datetime.datetime.fromisoformat({value!r})", raw_value=value)
|
|
64
|
+
return Value(python_code=PythonCode(f"datetime.datetime.fromisoformat({value!r})"), raw_value=value)
|
|
63
65
|
return PropertyError(f"Cannot convert {value} to a datetime")
|
|
64
66
|
|
|
65
67
|
def get_imports(self, *, prefix: str) -> set[str]:
|
|
@@ -5,14 +5,14 @@ __all__ = ["EnumProperty", "ValueType"]
|
|
|
5
5
|
from typing import Any, ClassVar, cast
|
|
6
6
|
|
|
7
7
|
from attr import evolve
|
|
8
|
-
from attrs import define
|
|
8
|
+
from attrs import define, field
|
|
9
9
|
|
|
10
|
-
from ... import Config,
|
|
10
|
+
from ... import Config, strings
|
|
11
11
|
from ... import schema as oai
|
|
12
12
|
from ...schema import DataType
|
|
13
13
|
from ..errors import PropertyError
|
|
14
14
|
from .none import NoneProperty
|
|
15
|
-
from .protocol import PropertyProtocol, Value
|
|
15
|
+
from .protocol import PropertyProtocol, Value, convert_example
|
|
16
16
|
from .schemas import Class, Schemas
|
|
17
17
|
from .union import UnionProperty
|
|
18
18
|
|
|
@@ -23,12 +23,12 @@ ValueType = str | int
|
|
|
23
23
|
class EnumProperty(PropertyProtocol):
|
|
24
24
|
"""A property that should use an enum"""
|
|
25
25
|
|
|
26
|
-
name:
|
|
26
|
+
name: oai.UntrustedString
|
|
27
27
|
required: bool
|
|
28
28
|
default: Value | None
|
|
29
|
-
python_name:
|
|
30
|
-
description:
|
|
31
|
-
example:
|
|
29
|
+
python_name: strings.PythonIdentifier
|
|
30
|
+
description: oai.UntrustedString | None
|
|
31
|
+
example: oai.UntrustedString | None = field(converter=convert_example)
|
|
32
32
|
values: dict[str, ValueType]
|
|
33
33
|
class_info: Class
|
|
34
34
|
value_type: type[ValueType]
|
|
@@ -47,7 +47,7 @@ class EnumProperty(PropertyProtocol):
|
|
|
47
47
|
cls,
|
|
48
48
|
*,
|
|
49
49
|
data: oai.Schema,
|
|
50
|
-
name:
|
|
50
|
+
name: oai.UntrustedString,
|
|
51
51
|
required: bool,
|
|
52
52
|
schemas: Schemas,
|
|
53
53
|
parent_name: str,
|
|
@@ -83,7 +83,7 @@ class EnumProperty(PropertyProtocol):
|
|
|
83
83
|
name=name,
|
|
84
84
|
required=required,
|
|
85
85
|
default="None",
|
|
86
|
-
python_name=
|
|
86
|
+
python_name=strings.PythonIdentifier(value=name, prefix=config.field_prefix),
|
|
87
87
|
description=None,
|
|
88
88
|
example=None,
|
|
89
89
|
),
|
|
@@ -115,9 +115,9 @@ class EnumProperty(PropertyProtocol):
|
|
|
115
115
|
config=config,
|
|
116
116
|
)
|
|
117
117
|
|
|
118
|
-
class_name = data.title or name
|
|
118
|
+
class_name: str | oai.UntrustedString = data.title or name
|
|
119
119
|
if parent_name:
|
|
120
|
-
class_name = f"{
|
|
120
|
+
class_name = f"{strings.pascal_case(parent_name)}{strings.pascal_case(class_name)}"
|
|
121
121
|
class_info = Class.from_string(string=class_name, config=config)
|
|
122
122
|
var_names = data.model_extra.get("x-enum-varnames", []) if data.model_extra else []
|
|
123
123
|
values = EnumProperty.values_from_list(value_list, class_info, var_names)
|
|
@@ -139,7 +139,7 @@ class EnumProperty(PropertyProtocol):
|
|
|
139
139
|
values=values,
|
|
140
140
|
value_type=value_type,
|
|
141
141
|
default=None,
|
|
142
|
-
python_name=
|
|
142
|
+
python_name=strings.PythonIdentifier(value=name, prefix=config.field_prefix),
|
|
143
143
|
description=data.description,
|
|
144
144
|
example=data.example,
|
|
145
145
|
)
|
|
@@ -158,16 +158,19 @@ class EnumProperty(PropertyProtocol):
|
|
|
158
158
|
if isinstance(value, self.value_type):
|
|
159
159
|
inverse_values = {v: k for k, v in self.values.items()}
|
|
160
160
|
try:
|
|
161
|
-
return Value(
|
|
161
|
+
return Value(
|
|
162
|
+
python_code=strings.PythonCode(f"{self.class_info.name}.{inverse_values[value]}"),
|
|
163
|
+
raw_value=value,
|
|
164
|
+
)
|
|
162
165
|
except KeyError:
|
|
163
166
|
return PropertyError(detail=f"Value {value} is not valid for enum {self.name}")
|
|
164
167
|
return PropertyError(detail=f"Cannot convert {value} to enum {self.name} of type {self.value_type}")
|
|
165
168
|
|
|
166
|
-
def get_base_type_string(self) ->
|
|
167
|
-
return self.class_info.name
|
|
169
|
+
def get_base_type_string(self) -> strings.PythonCode:
|
|
170
|
+
return strings.PythonCode(self.class_info.name)
|
|
168
171
|
|
|
169
|
-
def get_base_json_type_string(self) ->
|
|
170
|
-
return self.value_type.__name__
|
|
172
|
+
def get_base_json_type_string(self) -> strings.PythonCode:
|
|
173
|
+
return strings.PythonCode(self.value_type.__name__)
|
|
171
174
|
|
|
172
175
|
def get_imports(self, *, prefix: str) -> set[str]:
|
|
173
176
|
"""
|
|
@@ -194,7 +197,7 @@ class EnumProperty(PropertyProtocol):
|
|
|
194
197
|
if isinstance(value, int):
|
|
195
198
|
if use_var_names:
|
|
196
199
|
key = var_names[i]
|
|
197
|
-
sanitized_key =
|
|
200
|
+
sanitized_key = strings.snake_case(key).upper()
|
|
198
201
|
output[sanitized_key] = value
|
|
199
202
|
elif value < 0:
|
|
200
203
|
output[f"VALUE_NEGATIVE_{-value}"] = value
|
|
@@ -212,6 +215,6 @@ class EnumProperty(PropertyProtocol):
|
|
|
212
215
|
f"Duplicate key {key} in enum {class_info.module_name}.{class_info.name}; "
|
|
213
216
|
f"consider setting literal_enums in your config"
|
|
214
217
|
)
|
|
215
|
-
sanitized_key =
|
|
216
|
-
output[sanitized_key] =
|
|
218
|
+
sanitized_key = strings.snake_case(key).upper()
|
|
219
|
+
output[sanitized_key] = strings.in_double_quote_literal(value)
|
|
217
220
|
return output
|