openapi-python-client 0.28.4__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 +5 -3
- openapi_python_client/parser/bodies.py +14 -23
- 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 +15 -14
- openapi_python_client/parser/properties/datetime.py +15 -14
- 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/data_type.py +2 -2
- 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/parameter_location.py +7 -22
- 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 +20 -14
- openapi_python_client/templates/helpers.jinja +3 -7
- openapi_python_client/templates/literal_enum.py.jinja +3 -3
- 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 +2 -2
- openapi_python_client/templates/property_templates/datetime_property.py.jinja +2 -2
- 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 +4 -5
- openapi_python_client/templates/pyproject_poetry.toml.jinja +4 -5
- openapi_python_client/templates/pyproject_uv.toml.jinja +5 -6
- openapi_python_client/templates/setup.py.jinja +4 -4
- openapi_python_client/templates/str_enum.py.jinja +2 -2
- {openapi_python_client-0.28.4.dist-info → openapi_python_client-0.29.1.dist-info}/METADATA +6 -9
- openapi_python_client-0.29.1.dist-info/RECORD +115 -0
- {openapi_python_client-0.28.4.dist-info → openapi_python_client-0.29.1.dist-info}/WHEEL +1 -1
- openapi_python_client/utils.py +0 -122
- openapi_python_client-0.28.4.dist-info/RECORD +0 -113
- {openapi_python_client-0.28.4.dist-info → openapi_python_client-0.29.1.dist-info}/entry_points.txt +0 -0
- {openapi_python_client-0.28.4.dist-info → openapi_python_client-0.29.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -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
|
|
@@ -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
|
|