openapi-python-client 0.29.0__py3-none-any.whl → 0.29.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.
- openapi_python_client/__init__.py +26 -17
- openapi_python_client/cli.py +1 -2
- openapi_python_client/config.py +3 -1
- openapi_python_client/parser/bodies.py +8 -7
- openapi_python_client/parser/openapi.py +58 -48
- openapi_python_client/parser/properties/__init__.py +34 -33
- openapi_python_client/parser/properties/any.py +11 -10
- openapi_python_client/parser/properties/boolean.py +13 -13
- openapi_python_client/parser/properties/const.py +11 -10
- openapi_python_client/parser/properties/date.py +12 -11
- openapi_python_client/parser/properties/datetime.py +12 -11
- openapi_python_client/parser/properties/enum_property.py +23 -20
- openapi_python_client/parser/properties/file.py +11 -10
- openapi_python_client/parser/properties/float.py +13 -13
- openapi_python_client/parser/properties/int.py +11 -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 +34 -33
- openapi_python_client/parser/properties/none.py +11 -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 +10 -11
- openapi_python_client/parser/properties/union.py +24 -22
- openapi_python_client/parser/properties/uuid.py +11 -11
- openapi_python_client/parser/responses.py +30 -23
- 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 +7 -6
- 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 +3 -3
- openapi_python_client/templates/client.py.jinja +5 -5
- openapi_python_client/templates/endpoint_macros.py.jinja +18 -18
- openapi_python_client/templates/endpoint_module.py.jinja +13 -13
- 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 +2 -2
- openapi_python_client/templates/pyproject_poetry.toml.jinja +2 -2
- openapi_python_client/templates/pyproject_uv.toml.jinja +3 -3
- openapi_python_client/templates/setup.py.jinja +2 -2
- openapi_python_client/templates/str_enum.py.jinja +2 -2
- {openapi_python_client-0.29.0.dist-info → openapi_python_client-0.29.1.dist-info}/METADATA +4 -5
- openapi_python_client-0.29.1.dist-info/RECORD +115 -0
- {openapi_python_client-0.29.0.dist-info → openapi_python_client-0.29.1.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.29.1.dist-info}/entry_points.txt +0 -0
- {openapi_python_client-0.29.0.dist-info → openapi_python_client-0.29.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -2,23 +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
|
-
from ...
|
|
7
|
+
from ... import schema as oai
|
|
8
|
+
from ...strings import PythonIdentifier
|
|
8
9
|
from ..errors import PropertyError
|
|
9
|
-
from .protocol import PropertyProtocol
|
|
10
|
+
from .protocol import PropertyProtocol, convert_example
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
@define
|
|
13
14
|
class FileProperty(PropertyProtocol):
|
|
14
15
|
"""A property used for uploading files"""
|
|
15
16
|
|
|
16
|
-
name:
|
|
17
|
+
name: oai.UntrustedString
|
|
17
18
|
required: bool
|
|
18
19
|
default: None
|
|
19
20
|
python_name: PythonIdentifier
|
|
20
|
-
description:
|
|
21
|
-
example:
|
|
21
|
+
description: oai.UntrustedString | None
|
|
22
|
+
example: oai.UntrustedString | None = field(converter=convert_example)
|
|
22
23
|
|
|
23
24
|
_type_string: ClassVar[str] = "File"
|
|
24
25
|
# Return type of File.to_tuple()
|
|
@@ -28,12 +29,12 @@ class FileProperty(PropertyProtocol):
|
|
|
28
29
|
@classmethod
|
|
29
30
|
def build(
|
|
30
31
|
cls,
|
|
31
|
-
name:
|
|
32
|
+
name: oai.UntrustedString,
|
|
32
33
|
required: bool,
|
|
33
34
|
default: Any,
|
|
34
35
|
python_name: PythonIdentifier,
|
|
35
|
-
description:
|
|
36
|
-
example:
|
|
36
|
+
description: oai.UntrustedString | None,
|
|
37
|
+
example: Any,
|
|
37
38
|
) -> FileProperty | PropertyError:
|
|
38
39
|
default_or_err = cls.convert_value(default)
|
|
39
40
|
if isinstance(default_or_err, PropertyError):
|
|
@@ -49,7 +50,7 @@ class FileProperty(PropertyProtocol):
|
|
|
49
50
|
)
|
|
50
51
|
|
|
51
52
|
@classmethod
|
|
52
|
-
def convert_value(cls, value: Any) ->
|
|
53
|
+
def convert_value(cls, value: Any) -> PropertyError | None:
|
|
53
54
|
if value is not None:
|
|
54
55
|
return PropertyError(detail="File properties cannot have a default value")
|
|
55
56
|
return value
|
|
@@ -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 FloatProperty(PropertyProtocol):
|
|
15
15
|
"""A property of type float"""
|
|
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] = "float"
|
|
25
25
|
_json_type_string: ClassVar[str] = "float"
|
|
@@ -34,12 +34,12 @@ class FloatProperty(PropertyProtocol):
|
|
|
34
34
|
@classmethod
|
|
35
35
|
def build(
|
|
36
36
|
cls,
|
|
37
|
-
name:
|
|
37
|
+
name: oai.UntrustedString,
|
|
38
38
|
required: bool,
|
|
39
39
|
default: Any,
|
|
40
40
|
python_name: PythonIdentifier,
|
|
41
|
-
description:
|
|
42
|
-
example:
|
|
41
|
+
description: oai.UntrustedString | None,
|
|
42
|
+
example: Any,
|
|
43
43
|
) -> FloatProperty | PropertyError:
|
|
44
44
|
checked_default = cls.convert_value(default)
|
|
45
45
|
if isinstance(checked_default, PropertyError):
|
|
@@ -55,17 +55,17 @@ class FloatProperty(PropertyProtocol):
|
|
|
55
55
|
)
|
|
56
56
|
|
|
57
57
|
@classmethod
|
|
58
|
-
def convert_value(cls, value: Any) -> Value |
|
|
58
|
+
def convert_value(cls, value: Any) -> Value | PropertyError | None:
|
|
59
59
|
if isinstance(value, Value) or value is None:
|
|
60
60
|
return value
|
|
61
61
|
if isinstance(value, str):
|
|
62
62
|
try:
|
|
63
63
|
parsed = float(value)
|
|
64
|
-
return Value(python_code=str(parsed), raw_value=value)
|
|
64
|
+
return Value(python_code=PythonCode(str(parsed)), raw_value=value)
|
|
65
65
|
except ValueError:
|
|
66
66
|
return PropertyError(f"Invalid float value: {value}")
|
|
67
67
|
if isinstance(value, float):
|
|
68
|
-
return Value(python_code=str(value), raw_value=value)
|
|
68
|
+
return Value(python_code=PythonCode(str(value)), raw_value=value)
|
|
69
69
|
if isinstance(value, int) and not isinstance(value, bool):
|
|
70
|
-
return Value(python_code=str(float(value)), raw_value=value)
|
|
70
|
+
return Value(python_code=PythonCode(str(float(value))), raw_value=value)
|
|
71
71
|
return PropertyError(f"Cannot convert {value} to a float")
|
|
@@ -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 IntProperty(PropertyProtocol):
|
|
15
15
|
"""A property of type int"""
|
|
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] = "int"
|
|
25
25
|
_json_type_string: ClassVar[str] = "int"
|
|
@@ -34,12 +34,12 @@ class IntProperty(PropertyProtocol):
|
|
|
34
34
|
@classmethod
|
|
35
35
|
def build(
|
|
36
36
|
cls,
|
|
37
|
-
name:
|
|
37
|
+
name: oai.UntrustedString,
|
|
38
38
|
required: bool,
|
|
39
39
|
default: Any,
|
|
40
40
|
python_name: PythonIdentifier,
|
|
41
|
-
description:
|
|
42
|
-
example:
|
|
41
|
+
description: oai.UntrustedString | None,
|
|
42
|
+
example: Any,
|
|
43
43
|
) -> IntProperty | PropertyError:
|
|
44
44
|
checked_default = cls.convert_value(default)
|
|
45
45
|
if isinstance(checked_default, PropertyError):
|
|
@@ -55,7 +55,7 @@ class IntProperty(PropertyProtocol):
|
|
|
55
55
|
)
|
|
56
56
|
|
|
57
57
|
@classmethod
|
|
58
|
-
def convert_value(cls, value: Any) -> Value |
|
|
58
|
+
def convert_value(cls, value: Any) -> Value | PropertyError | None:
|
|
59
59
|
if value is None or isinstance(value, Value):
|
|
60
60
|
return value
|
|
61
61
|
converted = value
|
|
@@ -69,5 +69,5 @@ class IntProperty(PropertyProtocol):
|
|
|
69
69
|
if converted == as_int:
|
|
70
70
|
converted = as_int
|
|
71
71
|
if isinstance(converted, int) and not isinstance(converted, bool):
|
|
72
|
-
return Value(python_code=str(converted), raw_value=value)
|
|
72
|
+
return Value(python_code=PythonCode(str(converted)), raw_value=value)
|
|
73
73
|
return PropertyError(f"Invalid int value: {value}")
|
|
@@ -2,12 +2,12 @@ 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 ... import Config,
|
|
7
|
+
from ... import Config, strings
|
|
8
8
|
from ... import schema as oai
|
|
9
9
|
from ..errors import PropertyError
|
|
10
|
-
from .protocol import PropertyProtocol, Value
|
|
10
|
+
from .protocol import PropertyProtocol, Value, convert_example
|
|
11
11
|
from .schemas import ReferencePath, Schemas
|
|
12
12
|
|
|
13
13
|
|
|
@@ -15,12 +15,12 @@ from .schemas import ReferencePath, Schemas
|
|
|
15
15
|
class ListProperty(PropertyProtocol):
|
|
16
16
|
"""A property representing a list (array) of other properties"""
|
|
17
17
|
|
|
18
|
-
name:
|
|
18
|
+
name: oai.UntrustedString
|
|
19
19
|
required: bool
|
|
20
20
|
default: Value | None
|
|
21
|
-
python_name:
|
|
22
|
-
description:
|
|
23
|
-
example:
|
|
21
|
+
python_name: strings.PythonIdentifier
|
|
22
|
+
description: oai.UntrustedString | None
|
|
23
|
+
example: oai.UntrustedString | None = field(converter=convert_example)
|
|
24
24
|
inner_property: PropertyProtocol
|
|
25
25
|
template: ClassVar[str] = "list_property.py.jinja"
|
|
26
26
|
|
|
@@ -29,13 +29,13 @@ class ListProperty(PropertyProtocol):
|
|
|
29
29
|
cls,
|
|
30
30
|
*,
|
|
31
31
|
data: oai.Schema,
|
|
32
|
-
name:
|
|
32
|
+
name: oai.UntrustedString,
|
|
33
33
|
required: bool,
|
|
34
34
|
schemas: Schemas,
|
|
35
35
|
parent_name: str,
|
|
36
36
|
config: Config,
|
|
37
37
|
process_properties: bool,
|
|
38
|
-
roots: set[ReferencePath |
|
|
38
|
+
roots: set[ReferencePath | strings.ClassName],
|
|
39
39
|
) -> tuple[ListProperty | PropertyError, Schemas]:
|
|
40
40
|
"""
|
|
41
41
|
Build a ListProperty the right way, use this instead of the normal constructor.
|
|
@@ -77,7 +77,7 @@ class ListProperty(PropertyProtocol):
|
|
|
77
77
|
inner_schema = oai.Schema(anyOf=items)
|
|
78
78
|
|
|
79
79
|
inner_prop, schemas = property_from_data(
|
|
80
|
-
name=f"{name}_item",
|
|
80
|
+
name=oai.UntrustedString(f"{name.get_untrusted_value()}_item"),
|
|
81
81
|
required=True,
|
|
82
82
|
data=inner_schema,
|
|
83
83
|
schemas=schemas,
|
|
@@ -95,25 +95,25 @@ class ListProperty(PropertyProtocol):
|
|
|
95
95
|
required=required,
|
|
96
96
|
default=None,
|
|
97
97
|
inner_property=inner_prop,
|
|
98
|
-
python_name=
|
|
98
|
+
python_name=strings.PythonIdentifier(value=name, prefix=config.field_prefix),
|
|
99
99
|
description=data.description,
|
|
100
100
|
example=data.example,
|
|
101
101
|
),
|
|
102
102
|
schemas,
|
|
103
103
|
)
|
|
104
104
|
|
|
105
|
-
def convert_value(self, value: Any) -> Value |
|
|
105
|
+
def convert_value(self, value: Any) -> Value | PropertyError | None:
|
|
106
106
|
return None # pragma: no cover
|
|
107
107
|
|
|
108
|
-
def get_base_type_string(self) ->
|
|
109
|
-
return f"list[{self.inner_property.get_type_string()}]"
|
|
108
|
+
def get_base_type_string(self) -> strings.PythonCode:
|
|
109
|
+
return strings.PythonCode(f"list[{self.inner_property.get_type_string().as_unembedded_code()}]")
|
|
110
110
|
|
|
111
|
-
def get_base_json_type_string(self) ->
|
|
112
|
-
return f"list[{self.inner_property.get_type_string(json=True)}]"
|
|
111
|
+
def get_base_json_type_string(self) -> strings.PythonCode:
|
|
112
|
+
return strings.PythonCode(f"list[{self.inner_property.get_type_string(json=True).as_unembedded_code()}]")
|
|
113
113
|
|
|
114
|
-
def get_instance_type_string(self) ->
|
|
115
|
-
"""Get a
|
|
116
|
-
return "list"
|
|
114
|
+
def get_instance_type_string(self) -> strings.PythonCode:
|
|
115
|
+
"""Get a code representation of runtime type that should be used for `isinstance` checks"""
|
|
116
|
+
return strings.PythonCode("list")
|
|
117
117
|
|
|
118
118
|
def get_imports(self, *, prefix: str) -> set[str]:
|
|
119
119
|
"""
|
|
@@ -137,9 +137,9 @@ class ListProperty(PropertyProtocol):
|
|
|
137
137
|
self,
|
|
138
138
|
no_optional: bool = False,
|
|
139
139
|
json: bool = False,
|
|
140
|
-
) ->
|
|
140
|
+
) -> strings.PythonCode:
|
|
141
141
|
"""
|
|
142
|
-
Get a
|
|
142
|
+
Get a Python code representation of type that should be used when declaring this property
|
|
143
143
|
|
|
144
144
|
Args:
|
|
145
145
|
no_optional: Do not include Optional or Unset even if the value is optional (needed for isinstance checks)
|
|
@@ -152,4 +152,4 @@ class ListProperty(PropertyProtocol):
|
|
|
152
152
|
|
|
153
153
|
if no_optional or self.required:
|
|
154
154
|
return type_string
|
|
155
|
-
return f"{type_string} | Unset"
|
|
155
|
+
return strings.PythonCode(f"{type_string.as_unembedded_code()} | Unset")
|
|
@@ -5,14 +5,14 @@ __all__ = ["LiteralEnumProperty"]
|
|
|
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 LiteralEnumProperty(PropertyProtocol):
|
|
24
24
|
"""A property that should use a literal 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: set[ValueType]
|
|
33
33
|
class_info: Class
|
|
34
34
|
value_type: type[ValueType]
|
|
@@ -47,7 +47,7 @@ class LiteralEnumProperty(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,
|
|
@@ -82,7 +82,7 @@ class LiteralEnumProperty(PropertyProtocol):
|
|
|
82
82
|
name=name,
|
|
83
83
|
required=required,
|
|
84
84
|
default="None",
|
|
85
|
-
python_name=
|
|
85
|
+
python_name=strings.PythonIdentifier(value=name, prefix=config.field_prefix),
|
|
86
86
|
description=None,
|
|
87
87
|
example=None,
|
|
88
88
|
),
|
|
@@ -114,9 +114,9 @@ class LiteralEnumProperty(PropertyProtocol):
|
|
|
114
114
|
config=config,
|
|
115
115
|
)
|
|
116
116
|
|
|
117
|
-
class_name = data.title or name
|
|
117
|
+
class_name: str | oai.UntrustedString = data.title or name
|
|
118
118
|
if parent_name:
|
|
119
|
-
class_name = f"{
|
|
119
|
+
class_name = f"{strings.pascal_case(parent_name)}{strings.pascal_case(class_name)}"
|
|
120
120
|
class_info = Class.from_string(string=class_name, config=config)
|
|
121
121
|
values: set[str | int] = set(value_list)
|
|
122
122
|
|
|
@@ -137,7 +137,7 @@ class LiteralEnumProperty(PropertyProtocol):
|
|
|
137
137
|
values=values,
|
|
138
138
|
value_type=value_type,
|
|
139
139
|
default=None,
|
|
140
|
-
python_name=
|
|
140
|
+
python_name=strings.PythonIdentifier(value=name, prefix=config.field_prefix),
|
|
141
141
|
description=data.description,
|
|
142
142
|
example=data.example,
|
|
143
143
|
)
|
|
@@ -155,19 +155,19 @@ class LiteralEnumProperty(PropertyProtocol):
|
|
|
155
155
|
return value
|
|
156
156
|
if isinstance(value, self.value_type):
|
|
157
157
|
if value in self.values:
|
|
158
|
-
return Value(python_code=repr(value), raw_value=value)
|
|
158
|
+
return Value(python_code=strings.PythonCode(repr(value)), raw_value=value)
|
|
159
159
|
else:
|
|
160
160
|
return PropertyError(detail=f"Value {value} is not valid for enum {self.name}")
|
|
161
161
|
return PropertyError(detail=f"Cannot convert {value} to enum {self.name} of type {self.value_type}")
|
|
162
162
|
|
|
163
|
-
def get_base_type_string(self) ->
|
|
164
|
-
return self.class_info.name
|
|
163
|
+
def get_base_type_string(self) -> strings.PythonCode:
|
|
164
|
+
return strings.PythonCode(self.class_info.name)
|
|
165
165
|
|
|
166
|
-
def get_base_json_type_string(self) ->
|
|
167
|
-
return self.value_type.__name__
|
|
166
|
+
def get_base_json_type_string(self) -> strings.PythonCode:
|
|
167
|
+
return strings.PythonCode(self.value_type.__name__)
|
|
168
168
|
|
|
169
|
-
def get_instance_type_string(self) ->
|
|
170
|
-
return self.value_type.__name__
|
|
169
|
+
def get_instance_type_string(self) -> strings.PythonCode:
|
|
170
|
+
return strings.PythonCode(self.value_type.__name__)
|
|
171
171
|
|
|
172
172
|
def get_imports(self, *, prefix: str) -> set[str]:
|
|
173
173
|
"""
|
|
@@ -186,4 +186,4 @@ class LiteralEnumProperty(PropertyProtocol):
|
|
|
186
186
|
return imports
|
|
187
187
|
|
|
188
188
|
def get_class_name_snake_case(self) -> str:
|
|
189
|
-
return
|
|
189
|
+
return strings.snake_case(self.class_info.name)
|
|
@@ -67,11 +67,12 @@ def merge_properties(prop1: Property, prop2: Property) -> Property | PropertyErr
|
|
|
67
67
|
return merged
|
|
68
68
|
|
|
69
69
|
return PropertyError(
|
|
70
|
-
detail=f"{prop1.get_type_string(no_optional=True)} can't be merged with
|
|
70
|
+
detail=f"{prop1.get_type_string(no_optional=True).as_unembedded_code()} can't be merged with "
|
|
71
|
+
f"{prop2.get_type_string(no_optional=True).as_unembedded_code()}"
|
|
71
72
|
)
|
|
72
73
|
|
|
73
74
|
|
|
74
|
-
def _merge_same_type(prop1: Property, prop2: Property) -> Property |
|
|
75
|
+
def _merge_same_type(prop1: Property, prop2: Property) -> Property | PropertyError | None:
|
|
75
76
|
if type(prop1) is not type(prop2):
|
|
76
77
|
return None
|
|
77
78
|
|
|
@@ -90,7 +91,7 @@ def _merge_same_type(prop1: Property, prop2: Property) -> Property | None | Prop
|
|
|
90
91
|
return _merge_common_attributes(prop1, prop2)
|
|
91
92
|
|
|
92
93
|
|
|
93
|
-
def _merge_string_with_format(prop1: Property, prop2: Property) -> Property |
|
|
94
|
+
def _merge_string_with_format(prop1: Property, prop2: Property) -> Property | PropertyError | None:
|
|
94
95
|
"""Merge a string that has no format with a string that has a format"""
|
|
95
96
|
# Here we need to use the DateProperty/DateTimeProperty/FileProperty as the base so that we preserve
|
|
96
97
|
# its class, but keep the correct override order for merging the attributes.
|
|
@@ -103,7 +104,7 @@ def _merge_string_with_format(prop1: Property, prop2: Property) -> Property | No
|
|
|
103
104
|
return None
|
|
104
105
|
|
|
105
106
|
|
|
106
|
-
def _merge_numeric(prop1: Property, prop2: Property) -> IntProperty |
|
|
107
|
+
def _merge_numeric(prop1: Property, prop2: Property) -> IntProperty | PropertyError | None:
|
|
107
108
|
"""Merge IntProperty with FloatProperty"""
|
|
108
109
|
if isinstance(prop1, IntProperty) and isinstance(prop2, IntProperty | FloatProperty):
|
|
109
110
|
return _merge_common_attributes(prop1, prop2)
|
|
@@ -136,7 +137,8 @@ def _merge_with_enum(prop1: PropertyProtocol, prop2: PropertyProtocol) -> EnumPr
|
|
|
136
137
|
):
|
|
137
138
|
return _merge_common_attributes(enum_prop, prop1, prop2)
|
|
138
139
|
return PropertyError(
|
|
139
|
-
detail=f"can't combine enum of type {enum_prop.value_type} with
|
|
140
|
+
detail=f"can't combine enum of type {enum_prop.value_type} with "
|
|
141
|
+
f"{non_enum_prop.get_type_string(no_optional=True).as_unembedded_code()}"
|
|
140
142
|
)
|
|
141
143
|
|
|
142
144
|
|
|
@@ -162,7 +164,8 @@ def _merge_with_literal_enum(prop1: PropertyProtocol, prop2: PropertyProtocol) -
|
|
|
162
164
|
):
|
|
163
165
|
return _merge_common_attributes(enum_prop, prop1, prop2)
|
|
164
166
|
return PropertyError(
|
|
165
|
-
detail=f"can't combine literal enum of type {enum_prop.value_type} with
|
|
167
|
+
detail=f"can't combine literal enum of type {enum_prop.value_type} with "
|
|
168
|
+
f"{non_enum_prop.get_type_string(no_optional=True).as_unembedded_code()}"
|
|
166
169
|
)
|
|
167
170
|
|
|
168
171
|
|
|
@@ -3,14 +3,14 @@ from __future__ import annotations
|
|
|
3
3
|
from itertools import chain
|
|
4
4
|
from typing import Any, ClassVar, NamedTuple
|
|
5
5
|
|
|
6
|
-
from attrs import define, evolve
|
|
6
|
+
from attrs import define, evolve, field
|
|
7
7
|
|
|
8
|
-
from ... import Config,
|
|
8
|
+
from ... import Config, strings
|
|
9
9
|
from ... import schema as oai
|
|
10
|
-
from ...
|
|
10
|
+
from ...strings import PythonIdentifier
|
|
11
11
|
from ..errors import ParseError, PropertyError
|
|
12
12
|
from .any import AnyProperty
|
|
13
|
-
from .protocol import PropertyProtocol, Value
|
|
13
|
+
from .protocol import PropertyProtocol, Value, convert_example
|
|
14
14
|
from .schemas import Class, ReferencePath, Schemas, parse_reference_path
|
|
15
15
|
|
|
16
16
|
|
|
@@ -18,15 +18,15 @@ from .schemas import Class, ReferencePath, Schemas, parse_reference_path
|
|
|
18
18
|
class ModelProperty(PropertyProtocol):
|
|
19
19
|
"""A property which refers to another Schema"""
|
|
20
20
|
|
|
21
|
-
name:
|
|
21
|
+
name: oai.UntrustedString
|
|
22
22
|
required: bool
|
|
23
23
|
default: Value | None
|
|
24
|
-
python_name:
|
|
25
|
-
example:
|
|
24
|
+
python_name: strings.PythonIdentifier
|
|
25
|
+
example: oai.UntrustedString | None = field(converter=convert_example)
|
|
26
26
|
class_info: Class
|
|
27
27
|
data: oai.Schema
|
|
28
|
-
description:
|
|
29
|
-
roots: set[ReferencePath |
|
|
28
|
+
description: oai.UntrustedString | None
|
|
29
|
+
roots: set[ReferencePath | strings.ClassName]
|
|
30
30
|
required_properties: list[Property] | None
|
|
31
31
|
optional_properties: list[Property] | None
|
|
32
32
|
relative_imports: set[str] | None
|
|
@@ -43,13 +43,13 @@ class ModelProperty(PropertyProtocol):
|
|
|
43
43
|
cls,
|
|
44
44
|
*,
|
|
45
45
|
data: oai.Schema,
|
|
46
|
-
name:
|
|
46
|
+
name: oai.UntrustedString,
|
|
47
47
|
schemas: Schemas,
|
|
48
48
|
required: bool,
|
|
49
49
|
parent_name: str | None,
|
|
50
50
|
config: Config,
|
|
51
51
|
process_properties: bool,
|
|
52
|
-
roots: set[ReferencePath |
|
|
52
|
+
roots: set[ReferencePath | strings.ClassName],
|
|
53
53
|
) -> tuple[ModelProperty | PropertyError, Schemas]:
|
|
54
54
|
"""
|
|
55
55
|
A single ModelProperty from its OAI data
|
|
@@ -65,12 +65,13 @@ class ModelProperty(PropertyProtocol):
|
|
|
65
65
|
roots: Set of strings that identify schema objects on which the new ModelProperty will depend
|
|
66
66
|
process_properties: Determines whether the new ModelProperty will be initialized with property data
|
|
67
67
|
"""
|
|
68
|
+
class_string: str | oai.UntrustedString
|
|
68
69
|
if not config.use_path_prefixes_for_title_model_names and data.title:
|
|
69
70
|
class_string = data.title
|
|
70
71
|
else:
|
|
71
72
|
title = data.title or name
|
|
72
73
|
if parent_name:
|
|
73
|
-
class_string = f"{
|
|
74
|
+
class_string = f"{strings.pascal_case(parent_name)}{strings.pascal_case(title)}"
|
|
74
75
|
else:
|
|
75
76
|
class_string = title
|
|
76
77
|
class_info = Class.from_string(string=class_string, config=config)
|
|
@@ -92,7 +93,7 @@ class ModelProperty(PropertyProtocol):
|
|
|
92
93
|
relative_imports = property_data.relative_imports
|
|
93
94
|
lazy_imports = property_data.lazy_imports
|
|
94
95
|
for root in roots:
|
|
95
|
-
if isinstance(root,
|
|
96
|
+
if isinstance(root, strings.ClassName):
|
|
96
97
|
continue
|
|
97
98
|
schemas.add_dependencies(root, {class_info.name})
|
|
98
99
|
|
|
@@ -105,11 +106,11 @@ class ModelProperty(PropertyProtocol):
|
|
|
105
106
|
relative_imports=relative_imports,
|
|
106
107
|
lazy_imports=lazy_imports,
|
|
107
108
|
additional_properties=additional_properties,
|
|
108
|
-
description=data.description
|
|
109
|
+
description=data.description,
|
|
109
110
|
default=None,
|
|
110
111
|
required=required,
|
|
111
112
|
name=name,
|
|
112
|
-
python_name=
|
|
113
|
+
python_name=strings.PythonIdentifier(value=name, prefix=config.field_prefix),
|
|
113
114
|
example=data.example,
|
|
114
115
|
)
|
|
115
116
|
if class_info.name in schemas.classes_by_name:
|
|
@@ -126,7 +127,7 @@ class ModelProperty(PropertyProtocol):
|
|
|
126
127
|
return prop, schemas
|
|
127
128
|
|
|
128
129
|
@classmethod
|
|
129
|
-
def convert_value(cls, value: Any) -> Value |
|
|
130
|
+
def convert_value(cls, value: Any) -> Value | PropertyError | None:
|
|
130
131
|
if value is not None:
|
|
131
132
|
return PropertyError(detail="ModelProperty cannot have a default value") # pragma: no cover
|
|
132
133
|
return None
|
|
@@ -140,8 +141,8 @@ class ModelProperty(PropertyProtocol):
|
|
|
140
141
|
"""Constructs a self import statement from this ModelProperty's attributes"""
|
|
141
142
|
return f"models.{self.class_info.module_name} import {self.class_info.name}"
|
|
142
143
|
|
|
143
|
-
def get_base_type_string(self) ->
|
|
144
|
-
return self.class_info.name
|
|
144
|
+
def get_base_type_string(self) -> strings.PythonCode:
|
|
145
|
+
return strings.PythonCode(self.class_info.name)
|
|
145
146
|
|
|
146
147
|
def get_imports(self, *, prefix: str) -> set[str]:
|
|
147
148
|
"""
|
|
@@ -188,9 +189,9 @@ class ModelProperty(PropertyProtocol):
|
|
|
188
189
|
self,
|
|
189
190
|
no_optional: bool = False,
|
|
190
191
|
json: bool = False,
|
|
191
|
-
) ->
|
|
192
|
+
) -> strings.PythonCode:
|
|
192
193
|
"""
|
|
193
|
-
Get a
|
|
194
|
+
Get a Python code representation of type that should be used when declaring this property
|
|
194
195
|
|
|
195
196
|
Args:
|
|
196
197
|
no_optional: Do not include Optional or Unset even if the value is optional (needed for isinstance checks)
|
|
@@ -203,7 +204,7 @@ class ModelProperty(PropertyProtocol):
|
|
|
203
204
|
|
|
204
205
|
if no_optional or self.required:
|
|
205
206
|
return type_string
|
|
206
|
-
return f"{type_string} | Unset"
|
|
207
|
+
return strings.PythonCode(f"{type_string.as_unembedded_code()} | Unset")
|
|
207
208
|
|
|
208
209
|
|
|
209
210
|
from .property import Property # noqa: E402
|
|
@@ -232,14 +233,14 @@ def _process_properties( # noqa: PLR0912, PLR0911
|
|
|
232
233
|
*,
|
|
233
234
|
data: oai.Schema,
|
|
234
235
|
schemas: Schemas,
|
|
235
|
-
class_name:
|
|
236
|
+
class_name: strings.ClassName,
|
|
236
237
|
config: Config,
|
|
237
|
-
roots: set[ReferencePath |
|
|
238
|
+
roots: set[ReferencePath | strings.ClassName],
|
|
238
239
|
) -> _PropertyData | PropertyError:
|
|
239
240
|
from . import property_from_data # noqa: PLC0415
|
|
240
241
|
from .merge_properties import merge_properties # noqa: PLC0415
|
|
241
242
|
|
|
242
|
-
properties: dict[
|
|
243
|
+
properties: dict[oai.UntrustedString, Property] = {}
|
|
243
244
|
relative_imports: set[str] = set()
|
|
244
245
|
lazy_imports: set[str] = set()
|
|
245
246
|
required_set = set(data.required or [])
|
|
@@ -265,7 +266,7 @@ def _process_properties( # noqa: PLR0912, PLR0911
|
|
|
265
266
|
properties[merged_prop.name] = merged_prop
|
|
266
267
|
return None
|
|
267
268
|
|
|
268
|
-
unprocessed_props: list[tuple[
|
|
269
|
+
unprocessed_props: list[tuple[oai.UntrustedString, oai.Reference | oai.Schema]] = (
|
|
269
270
|
list(data.properties.items()) if data.properties else []
|
|
270
271
|
)
|
|
271
272
|
for sub_prop in data.allOf:
|
|
@@ -275,7 +276,7 @@ def _process_properties( # noqa: PLR0912, PLR0911
|
|
|
275
276
|
return PropertyError(detail=ref_path.detail, data=sub_prop)
|
|
276
277
|
sub_model = schemas.classes_by_reference.get(ref_path)
|
|
277
278
|
if sub_model is None:
|
|
278
|
-
return PropertyError(f"Reference {sub_prop.ref} not found")
|
|
279
|
+
return PropertyError(f"Reference {sub_prop.ref.get_untrusted_value()} not found")
|
|
279
280
|
if not isinstance(sub_model, ModelProperty):
|
|
280
281
|
return PropertyError("Cannot take allOf a non-object")
|
|
281
282
|
# Properties of allOf references first should be processed first
|
|
@@ -335,10 +336,10 @@ def _process_properties( # noqa: PLR0912, PLR0911
|
|
|
335
336
|
|
|
336
337
|
|
|
337
338
|
ANY_ADDITIONAL_PROPERTY = AnyProperty.build(
|
|
338
|
-
name="additional",
|
|
339
|
+
name=oai.UntrustedString("additional"),
|
|
339
340
|
required=True,
|
|
340
341
|
default=None,
|
|
341
|
-
description=
|
|
342
|
+
description=None,
|
|
342
343
|
python_name=PythonIdentifier(value="additional", prefix=""),
|
|
343
344
|
example=None,
|
|
344
345
|
)
|
|
@@ -348,10 +349,10 @@ def _get_additional_properties(
|
|
|
348
349
|
*,
|
|
349
350
|
schema_additional: None | (bool | (oai.Reference | oai.Schema)),
|
|
350
351
|
schemas: Schemas,
|
|
351
|
-
class_name:
|
|
352
|
+
class_name: strings.ClassName,
|
|
352
353
|
config: Config,
|
|
353
|
-
roots: set[ReferencePath |
|
|
354
|
-
) -> tuple[Property |
|
|
354
|
+
roots: set[ReferencePath | strings.ClassName],
|
|
355
|
+
) -> tuple[Property | PropertyError | None, Schemas]:
|
|
355
356
|
from . import property_from_data # noqa: PLC0415
|
|
356
357
|
|
|
357
358
|
if schema_additional is None:
|
|
@@ -367,7 +368,7 @@ def _get_additional_properties(
|
|
|
367
368
|
return ANY_ADDITIONAL_PROPERTY, schemas
|
|
368
369
|
|
|
369
370
|
additional_properties, schemas = property_from_data(
|
|
370
|
-
name="AdditionalProperty",
|
|
371
|
+
name=oai.UntrustedString("AdditionalProperty"),
|
|
371
372
|
required=True, # in the sense that if present in the dict will not be None
|
|
372
373
|
data=schema_additional,
|
|
373
374
|
schemas=schemas,
|
|
@@ -384,7 +385,7 @@ def _process_property_data(
|
|
|
384
385
|
schemas: Schemas,
|
|
385
386
|
class_info: Class,
|
|
386
387
|
config: Config,
|
|
387
|
-
roots: set[ReferencePath |
|
|
388
|
+
roots: set[ReferencePath | strings.ClassName],
|
|
388
389
|
) -> tuple[tuple[_PropertyData, Property | None] | PropertyError, Schemas]:
|
|
389
390
|
property_data = _process_properties(
|
|
390
391
|
data=data, schemas=schemas, class_name=class_info.name, config=config, roots=roots
|