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.
Files changed (92) hide show
  1. openapi_python_client/__init__.py +26 -17
  2. openapi_python_client/cli.py +1 -2
  3. openapi_python_client/config.py +5 -3
  4. openapi_python_client/parser/bodies.py +14 -23
  5. openapi_python_client/parser/openapi.py +58 -48
  6. openapi_python_client/parser/properties/__init__.py +34 -33
  7. openapi_python_client/parser/properties/any.py +11 -10
  8. openapi_python_client/parser/properties/boolean.py +13 -13
  9. openapi_python_client/parser/properties/const.py +11 -10
  10. openapi_python_client/parser/properties/date.py +15 -14
  11. openapi_python_client/parser/properties/datetime.py +15 -14
  12. openapi_python_client/parser/properties/enum_property.py +23 -20
  13. openapi_python_client/parser/properties/file.py +11 -10
  14. openapi_python_client/parser/properties/float.py +13 -13
  15. openapi_python_client/parser/properties/int.py +11 -11
  16. openapi_python_client/parser/properties/list_property.py +22 -22
  17. openapi_python_client/parser/properties/literal_enum_property.py +20 -20
  18. openapi_python_client/parser/properties/merge_properties.py +9 -6
  19. openapi_python_client/parser/properties/model_property.py +34 -33
  20. openapi_python_client/parser/properties/none.py +11 -11
  21. openapi_python_client/parser/properties/protocol.py +42 -32
  22. openapi_python_client/parser/properties/schemas.py +30 -23
  23. openapi_python_client/parser/properties/string.py +10 -11
  24. openapi_python_client/parser/properties/union.py +24 -22
  25. openapi_python_client/parser/properties/uuid.py +11 -11
  26. openapi_python_client/parser/responses.py +30 -23
  27. openapi_python_client/schema/__init__.py +2 -1
  28. openapi_python_client/schema/data_type.py +2 -2
  29. openapi_python_client/schema/openapi_schema_pydantic/callback.py +3 -1
  30. openapi_python_client/schema/openapi_schema_pydantic/components.py +10 -9
  31. openapi_python_client/schema/openapi_schema_pydantic/contact.py +5 -3
  32. openapi_python_client/schema/openapi_schema_pydantic/discriminator.py +4 -2
  33. openapi_python_client/schema/openapi_schema_pydantic/encoding.py +4 -3
  34. openapi_python_client/schema/openapi_schema_pydantic/example.py +5 -3
  35. openapi_python_client/schema/openapi_schema_pydantic/external_documentation.py +4 -2
  36. openapi_python_client/schema/openapi_schema_pydantic/header.py +20 -6
  37. openapi_python_client/schema/openapi_schema_pydantic/info.py +5 -4
  38. openapi_python_client/schema/openapi_schema_pydantic/license.py +4 -2
  39. openapi_python_client/schema/openapi_schema_pydantic/link.py +5 -4
  40. openapi_python_client/schema/openapi_schema_pydantic/media_type.py +3 -2
  41. openapi_python_client/schema/openapi_schema_pydantic/oauth_flow.py +6 -4
  42. openapi_python_client/schema/openapi_schema_pydantic/open_api.py +5 -3
  43. openapi_python_client/schema/openapi_schema_pydantic/operation.py +6 -5
  44. openapi_python_client/schema/openapi_schema_pydantic/parameter.py +6 -5
  45. openapi_python_client/schema/openapi_schema_pydantic/path_item.py +5 -3
  46. openapi_python_client/schema/openapi_schema_pydantic/paths.py +2 -1
  47. openapi_python_client/schema/openapi_schema_pydantic/reference.py +3 -1
  48. openapi_python_client/schema/openapi_schema_pydantic/request_body.py +3 -2
  49. openapi_python_client/schema/openapi_schema_pydantic/response.py +5 -4
  50. openapi_python_client/schema/openapi_schema_pydantic/responses.py +2 -1
  51. openapi_python_client/schema/openapi_schema_pydantic/schema.py +7 -6
  52. openapi_python_client/schema/openapi_schema_pydantic/security_requirement.py +3 -1
  53. openapi_python_client/schema/openapi_schema_pydantic/security_scheme.py +8 -7
  54. openapi_python_client/schema/openapi_schema_pydantic/server.py +4 -3
  55. openapi_python_client/schema/openapi_schema_pydantic/server_variable.py +5 -3
  56. openapi_python_client/schema/openapi_schema_pydantic/tag.py +3 -2
  57. openapi_python_client/schema/openapi_schema_pydantic/xml.py +5 -3
  58. openapi_python_client/schema/parameter_location.py +7 -22
  59. openapi_python_client/schema/ref.py +52 -0
  60. openapi_python_client/schema/untrusted_string.py +56 -0
  61. openapi_python_client/strings.py +245 -0
  62. openapi_python_client/templates/README.md.jinja +3 -3
  63. openapi_python_client/templates/client.py.jinja +5 -5
  64. openapi_python_client/templates/endpoint_macros.py.jinja +18 -18
  65. openapi_python_client/templates/endpoint_module.py.jinja +20 -14
  66. openapi_python_client/templates/helpers.jinja +3 -7
  67. openapi_python_client/templates/literal_enum.py.jinja +3 -3
  68. openapi_python_client/templates/model.py.jinja +18 -18
  69. openapi_python_client/templates/package_init.py.jinja +2 -2
  70. openapi_python_client/templates/property_templates/const_property.py.jinja +3 -3
  71. openapi_python_client/templates/property_templates/date_property.py.jinja +2 -2
  72. openapi_python_client/templates/property_templates/datetime_property.py.jinja +2 -2
  73. openapi_python_client/templates/property_templates/enum_property.py.jinja +1 -1
  74. openapi_python_client/templates/property_templates/file_property.py.jinja +1 -1
  75. openapi_python_client/templates/property_templates/list_property.py.jinja +3 -3
  76. openapi_python_client/templates/property_templates/literal_enum_property.py.jinja +2 -2
  77. openapi_python_client/templates/property_templates/model_property.py.jinja +1 -1
  78. openapi_python_client/templates/property_templates/property_macros.py.jinja +1 -1
  79. openapi_python_client/templates/property_templates/union_property.py.jinja +9 -9
  80. openapi_python_client/templates/property_templates/uuid_property.py.jinja +1 -1
  81. openapi_python_client/templates/pyproject_pdm.toml.jinja +4 -5
  82. openapi_python_client/templates/pyproject_poetry.toml.jinja +4 -5
  83. openapi_python_client/templates/pyproject_uv.toml.jinja +5 -6
  84. openapi_python_client/templates/setup.py.jinja +4 -4
  85. openapi_python_client/templates/str_enum.py.jinja +2 -2
  86. {openapi_python_client-0.28.4.dist-info → openapi_python_client-0.29.1.dist-info}/METADATA +6 -9
  87. openapi_python_client-0.29.1.dist-info/RECORD +115 -0
  88. {openapi_python_client-0.28.4.dist-info → openapi_python_client-0.29.1.dist-info}/WHEEL +1 -1
  89. openapi_python_client/utils.py +0 -122
  90. openapi_python_client-0.28.4.dist-info/RECORD +0 -113
  91. {openapi_python_client-0.28.4.dist-info → openapi_python_client-0.29.1.dist-info}/entry_points.txt +0 -0
  92. {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, utils
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: str
26
+ name: oai.UntrustedString
27
27
  required: bool
28
28
  default: Value | None
29
- python_name: utils.PythonIdentifier
30
- description: str | None
31
- example: str | None
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: str,
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=utils.PythonIdentifier(value=name, prefix=config.field_prefix),
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"{utils.pascal_case(parent_name)}{utils.pascal_case(class_name)}"
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=utils.PythonIdentifier(value=name, prefix=config.field_prefix),
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(python_code=f"{self.class_info.name}.{inverse_values[value]}", raw_value=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) -> str:
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) -> str:
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 = utils.snake_case(key).upper()
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 = utils.snake_case(key).upper()
216
- output[sanitized_key] = utils.remove_string_escapes(value)
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 ...utils import PythonIdentifier
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: str
17
+ name: oai.UntrustedString
17
18
  required: bool
18
19
  default: None
19
20
  python_name: PythonIdentifier
20
- description: str | None
21
- example: str | None
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: str,
32
+ name: oai.UntrustedString,
32
33
  required: bool,
33
34
  default: Any,
34
35
  python_name: PythonIdentifier,
35
- description: str | None,
36
- example: str | None,
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) -> None | PropertyError:
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 ...utils import PythonIdentifier
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: str
17
+ name: oai.UntrustedString
18
18
  required: bool
19
19
  default: Value | None
20
20
  python_name: PythonIdentifier
21
- description: str | None
22
- example: str | None
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: str,
37
+ name: oai.UntrustedString,
38
38
  required: bool,
39
39
  default: Any,
40
40
  python_name: PythonIdentifier,
41
- description: str | None,
42
- example: str | None,
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 | None | PropertyError:
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 ...utils import PythonIdentifier
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: str
17
+ name: oai.UntrustedString
18
18
  required: bool
19
19
  default: Value | None
20
20
  python_name: PythonIdentifier
21
- description: str | None
22
- example: str | None
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: str,
37
+ name: oai.UntrustedString,
38
38
  required: bool,
39
39
  default: Any,
40
40
  python_name: PythonIdentifier,
41
- description: str | None,
42
- example: str | None,
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 | None | PropertyError:
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, utils
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: str
18
+ name: oai.UntrustedString
19
19
  required: bool
20
20
  default: Value | None
21
- python_name: utils.PythonIdentifier
22
- description: str | None
23
- example: str | None
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: str,
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 | utils.ClassName],
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=utils.PythonIdentifier(value=name, prefix=config.field_prefix),
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 | None | PropertyError:
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) -> str:
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) -> str:
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) -> str:
115
- """Get a string representation of runtime type that should be used for `isinstance` checks"""
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
- ) -> str:
140
+ ) -> strings.PythonCode:
141
141
  """
142
- Get a string representation of type that should be used when declaring this property
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, utils
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: str
26
+ name: oai.UntrustedString
27
27
  required: bool
28
28
  default: Value | None
29
- python_name: utils.PythonIdentifier
30
- description: str | None
31
- example: str | None
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: str,
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=utils.PythonIdentifier(value=name, prefix=config.field_prefix),
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"{utils.pascal_case(parent_name)}{utils.pascal_case(class_name)}"
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=utils.PythonIdentifier(value=name, prefix=config.field_prefix),
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) -> str:
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) -> str:
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) -> str:
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 utils.snake_case(self.class_info.name)
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 {prop2.get_type_string(no_optional=True)}"
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 | None | PropertyError:
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 | None | PropertyError:
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 | None | PropertyError:
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 {non_enum_prop.get_type_string(no_optional=True)}"
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 {non_enum_prop.get_type_string(no_optional=True)}"
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