openapi-python-client 0.26.2__tar.gz → 0.27.1__tar.gz

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 (113) hide show
  1. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/PKG-INFO +6 -7
  2. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/README.md +1 -1
  3. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/__init__.py +8 -8
  4. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/cli.py +13 -14
  5. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/config.py +17 -18
  6. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/parser/bodies.py +5 -6
  7. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/parser/errors.py +2 -3
  8. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/parser/openapi.py +22 -22
  9. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/parser/properties/const.py +2 -4
  10. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/parser/properties/enum_property.py +6 -8
  11. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/parser/properties/list_property.py +5 -7
  12. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/parser/properties/literal_enum_property.py +5 -7
  13. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/parser/properties/merge_properties.py +2 -2
  14. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/parser/properties/model_property.py +3 -9
  15. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/parser/properties/property.py +19 -20
  16. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/parser/properties/protocol.py +10 -25
  17. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/parser/properties/schemas.py +11 -11
  18. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/parser/properties/union.py +4 -7
  19. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/parser/responses.py +11 -11
  20. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/components.py +9 -11
  21. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/contact.py +3 -5
  22. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/discriminator.py +1 -3
  23. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/encoding.py +4 -4
  24. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/example.py +5 -5
  25. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/external_documentation.py +1 -3
  26. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/info.py +4 -6
  27. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/license.py +1 -3
  28. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/link.py +7 -7
  29. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/media_type.py +5 -5
  30. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/oauth_flow.py +3 -5
  31. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/oauth_flows.py +4 -6
  32. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/open_api.py +4 -6
  33. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/operation.py +10 -12
  34. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/parameter.py +7 -7
  35. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/path_item.py +14 -14
  36. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/reference.py +2 -3
  37. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/request_body.py +1 -3
  38. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/response.py +3 -5
  39. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/schema.py +33 -33
  40. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/security_scheme.py +7 -9
  41. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/server.py +2 -4
  42. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/server_variable.py +2 -4
  43. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/tag.py +2 -4
  44. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/xml.py +3 -5
  45. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/client.py.jinja +7 -7
  46. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/endpoint_macros.py.jinja +6 -6
  47. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/endpoint_module.py.jinja +6 -6
  48. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/model.py.jinja +4 -2
  49. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/property_templates/list_property.py.jinja +10 -4
  50. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/property_templates/union_property.py.jinja +1 -1
  51. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/pyproject_pdm.toml.jinja +1 -1
  52. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/pyproject_poetry.toml.jinja +2 -2
  53. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/pyproject_uv.toml.jinja +2 -5
  54. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/setup.py.jinja +1 -1
  55. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/types.py.jinja +9 -9
  56. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/pyproject.toml +6 -7
  57. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/.gitignore +0 -0
  58. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/LICENSE +0 -0
  59. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/__main__.py +0 -0
  60. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/parser/__init__.py +0 -0
  61. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/parser/properties/__init__.py +0 -0
  62. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/parser/properties/any.py +0 -0
  63. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/parser/properties/boolean.py +0 -0
  64. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/parser/properties/date.py +0 -0
  65. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/parser/properties/datetime.py +0 -0
  66. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/parser/properties/file.py +0 -0
  67. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/parser/properties/float.py +0 -0
  68. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/parser/properties/int.py +0 -0
  69. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/parser/properties/none.py +0 -0
  70. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/parser/properties/string.py +0 -0
  71. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/parser/properties/uuid.py +0 -0
  72. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/py.typed +0 -0
  73. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/3.0.3.md +0 -0
  74. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/3.1.0.md +0 -0
  75. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/__init__.py +0 -0
  76. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/data_type.py +0 -0
  77. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/LICENSE +0 -0
  78. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/README.md +0 -0
  79. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/__init__.py +0 -0
  80. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/callback.py +0 -0
  81. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/header.py +0 -0
  82. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/paths.py +0 -0
  83. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/responses.py +0 -0
  84. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/openapi_schema_pydantic/security_requirement.py +0 -0
  85. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/schema/parameter_location.py +0 -0
  86. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/.gitignore.jinja +0 -0
  87. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/README.md.jinja +0 -0
  88. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/api_init.py.jinja +0 -0
  89. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/endpoint_init.py.jinja +0 -0
  90. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/errors.py.jinja +0 -0
  91. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/helpers.jinja +0 -0
  92. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/int_enum.py.jinja +0 -0
  93. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/literal_enum.py.jinja +0 -0
  94. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/models_init.py.jinja +0 -0
  95. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/package_init.py.jinja +0 -0
  96. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/property_templates/any_property.py.jinja +0 -0
  97. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/property_templates/boolean_property.py.jinja +0 -0
  98. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/property_templates/const_property.py.jinja +0 -0
  99. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/property_templates/date_property.py.jinja +0 -0
  100. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/property_templates/datetime_property.py.jinja +0 -0
  101. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/property_templates/enum_property.py.jinja +0 -0
  102. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/property_templates/file_property.py.jinja +0 -0
  103. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/property_templates/float_property.py.jinja +0 -0
  104. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/property_templates/helpers.jinja +0 -0
  105. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/property_templates/int_property.py.jinja +0 -0
  106. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/property_templates/literal_enum_property.py.jinja +0 -0
  107. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/property_templates/model_property.py.jinja +0 -0
  108. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/property_templates/property_macros.py.jinja +0 -0
  109. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/property_templates/uuid_property.py.jinja +0 -0
  110. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/pyproject.toml.jinja +0 -0
  111. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/pyproject_ruff.toml.jinja +0 -0
  112. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/templates/str_enum.py.jinja +0 -0
  113. {openapi_python_client-0.26.2 → openapi_python_client-0.27.1}/openapi_python_client/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openapi-python-client
3
- Version: 0.26.2
3
+ Version: 0.27.1
4
4
  Summary: Generate modern Python clients from OpenAPI
5
5
  Project-URL: repository, https://github.com/openapi-generators/openapi-python-client
6
6
  Author-email: Dylan Anthony <contact@dylananthony.com>
@@ -11,14 +11,14 @@ Classifier: Development Status :: 4 - Beta
11
11
  Classifier: Intended Audience :: Developers
12
12
  Classifier: License :: OSI Approved :: MIT License
13
13
  Classifier: Programming Language :: Python :: 3
14
- Classifier: Programming Language :: Python :: 3.9
15
14
  Classifier: Programming Language :: Python :: 3.10
16
15
  Classifier: Programming Language :: Python :: 3.11
17
16
  Classifier: Programming Language :: Python :: 3.12
18
17
  Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
19
  Classifier: Topic :: Software Development :: Code Generators
20
20
  Classifier: Typing :: Typed
21
- Requires-Python: <4.0,>=3.9
21
+ Requires-Python: <4.0,>=3.10
22
22
  Requires-Dist: attrs>=22.2.0
23
23
  Requires-Dist: colorama>=0.4.3; sys_platform == 'win32'
24
24
  Requires-Dist: httpx<0.29.0,>=0.23.0
@@ -26,10 +26,9 @@ Requires-Dist: jinja2<4.0.0,>=3.0.0
26
26
  Requires-Dist: pydantic<3.0.0,>=2.10
27
27
  Requires-Dist: python-dateutil<3.0.0,>=2.8.1
28
28
  Requires-Dist: ruamel-yaml<0.19.0,>=0.18.6
29
- Requires-Dist: ruff<0.14,>=0.2
29
+ Requires-Dist: ruff>=0.2
30
30
  Requires-Dist: shellingham<2.0.0,>=1.3.2
31
- Requires-Dist: typer<0.20,>0.6
32
- Requires-Dist: typing-extensions<5.0.0,>=4.8.0
31
+ Requires-Dist: typer<0.21,>0.16
33
32
  Description-Content-Type: text/markdown
34
33
 
35
34
  ![Run Checks](https://github.com/openapi-generators/openapi-python-client/workflows/Run%20Checks/badge.svg)
@@ -200,7 +199,7 @@ In the config file, there's an easy way to tell `openapi-python-client` to run a
200
199
 
201
200
  ```yaml
202
201
  post_hooks:
203
- - "ruff check . --fix"
202
+ - "ruff check . --fix-only"
204
203
  - "ruff format ."
205
204
  ```
206
205
 
@@ -166,7 +166,7 @@ In the config file, there's an easy way to tell `openapi-python-client` to run a
166
166
 
167
167
  ```yaml
168
168
  post_hooks:
169
- - "ruff check . --fix"
169
+ - "ruff check . --fix-only"
170
170
  - "ruff format ."
171
171
  ```
172
172
 
@@ -8,7 +8,7 @@ from collections.abc import Sequence
8
8
  from importlib.metadata import version
9
9
  from pathlib import Path
10
10
  from subprocess import CalledProcessError
11
- from typing import Any, Optional, Union
11
+ from typing import Any
12
12
 
13
13
  import httpcore
14
14
  import httpx
@@ -42,7 +42,7 @@ class Project:
42
42
  *,
43
43
  openapi: GeneratorData,
44
44
  config: Config,
45
- custom_template_path: Optional[Path] = None,
45
+ custom_template_path: Path | None = None,
46
46
  ) -> None:
47
47
  self.openapi: GeneratorData = openapi
48
48
  self.config = config
@@ -292,8 +292,8 @@ class Project:
292
292
 
293
293
  def _get_project_for_url_or_path(
294
294
  config: Config,
295
- custom_template_path: Optional[Path] = None,
296
- ) -> Union[Project, GeneratorError]:
295
+ custom_template_path: Path | None = None,
296
+ ) -> Project | GeneratorError:
297
297
  data_dict = _get_document(source=config.document_source, timeout=config.http_timeout)
298
298
  if isinstance(data_dict, GeneratorError):
299
299
  return data_dict
@@ -310,7 +310,7 @@ def _get_project_for_url_or_path(
310
310
  def generate(
311
311
  *,
312
312
  config: Config,
313
- custom_template_path: Optional[Path] = None,
313
+ custom_template_path: Path | None = None,
314
314
  ) -> Sequence[GeneratorError]:
315
315
  """
316
316
  Generate the client library
@@ -327,7 +327,7 @@ def generate(
327
327
  return project.build()
328
328
 
329
329
 
330
- def _load_yaml_or_json(data: bytes, content_type: Optional[str]) -> Union[dict[str, Any], GeneratorError]:
330
+ def _load_yaml_or_json(data: bytes, content_type: str | None) -> dict[str, Any] | GeneratorError:
331
331
  if content_type == "application/json":
332
332
  try:
333
333
  return json.loads(data.decode())
@@ -341,9 +341,9 @@ def _load_yaml_or_json(data: bytes, content_type: Optional[str]) -> Union[dict[s
341
341
  return GeneratorError(header=f"Invalid YAML from provided source: {err}")
342
342
 
343
343
 
344
- def _get_document(*, source: Union[str, Path], timeout: int) -> Union[dict[str, Any], GeneratorError]:
344
+ def _get_document(*, source: str | Path, timeout: int) -> dict[str, Any] | GeneratorError:
345
345
  yaml_bytes: bytes
346
- content_type: Optional[str]
346
+ content_type: str | None
347
347
  if isinstance(source, str):
348
348
  try:
349
349
  response = httpx.get(source, timeout=timeout)
@@ -2,7 +2,6 @@ import codecs
2
2
  from collections.abc import Sequence
3
3
  from pathlib import Path
4
4
  from pprint import pformat
5
- from typing import Optional, Union
6
5
 
7
6
  import typer
8
7
 
@@ -21,15 +20,15 @@ def _version_callback(value: bool) -> None:
21
20
 
22
21
  def _process_config(
23
22
  *,
24
- url: Optional[str],
25
- path: Optional[Path],
26
- config_path: Optional[Path],
23
+ url: str | None,
24
+ path: Path | None,
25
+ config_path: Path | None,
27
26
  meta_type: MetaType,
28
27
  file_encoding: str,
29
28
  overwrite: bool,
30
- output_path: Optional[Path],
29
+ output_path: Path | None,
31
30
  ) -> Config:
32
- source: Union[Path, str]
31
+ source: Path | str
33
32
  if url and not path:
34
33
  source = url
35
34
  elif path and not url:
@@ -70,16 +69,16 @@ def cli(
70
69
 
71
70
  def _print_parser_error(err: GeneratorError, color: str) -> None:
72
71
  typer.secho(err.header, bold=True, fg=color, err=True)
73
- typer.echo()
72
+ typer.echo(err=True)
74
73
  if err.detail:
75
74
  typer.secho(err.detail, fg=color, err=True)
76
- typer.echo()
75
+ typer.echo(err=True)
77
76
 
78
77
  if isinstance(err, ParseError) and err.data is not None:
79
78
  formatted_data = pformat(err.data)
80
79
  typer.secho(formatted_data, fg=color, err=True)
81
80
 
82
- typer.echo()
81
+ typer.echo(err=True)
83
82
 
84
83
 
85
84
  def handle_errors(errors: Sequence[GeneratorError], fail_on_warning: bool = False) -> None:
@@ -125,9 +124,9 @@ def handle_errors(errors: Sequence[GeneratorError], fail_on_warning: bool = Fals
125
124
 
126
125
  @app.command()
127
126
  def generate(
128
- url: Optional[str] = typer.Option(None, help="A URL to read the OpenAPI document from"),
129
- path: Optional[Path] = typer.Option(None, help="A path to the OpenAPI document"),
130
- custom_template_path: Optional[Path] = typer.Option(
127
+ url: str | None = typer.Option(None, help="A URL to read the OpenAPI document from"),
128
+ path: Path | None = typer.Option(None, help="A path to the OpenAPI document"),
129
+ custom_template_path: Path | None = typer.Option(
131
130
  None,
132
131
  help="A path to a directory containing custom template(s)",
133
132
  file_okay=False,
@@ -140,10 +139,10 @@ def generate(
140
139
  help="The type of metadata you want to generate.",
141
140
  ),
142
141
  file_encoding: str = typer.Option("utf-8", help="Encoding used when writing generated"),
143
- config_path: Optional[Path] = typer.Option(None, "--config", help="Path to the config file to use"),
142
+ config_path: Path | None = typer.Option(None, "--config", help="Path to the config file to use"),
144
143
  fail_on_warning: bool = False,
145
144
  overwrite: bool = typer.Option(False, help="Overwrite the existing client if it exists"),
146
- output_path: Optional[Path] = typer.Option(
145
+ output_path: Path | None = typer.Option(
147
146
  None,
148
147
  help="Path to write the generated code to. "
149
148
  "Defaults to the OpenAPI document title converted to kebab or snake case (depending on meta type). "
@@ -2,7 +2,6 @@ import json
2
2
  import mimetypes
3
3
  from enum import Enum
4
4
  from pathlib import Path
5
- from typing import Optional, Union
6
5
 
7
6
  from attr import define
8
7
  from pydantic import BaseModel
@@ -15,8 +14,8 @@ class ClassOverride(BaseModel):
15
14
  See https://github.com/openapi-generators/openapi-python-client#class_overrides
16
15
  """
17
16
 
18
- class_name: Optional[str] = None
19
- module_name: Optional[str] = None
17
+ class_name: str | None = None
18
+ module_name: str | None = None
20
19
 
21
20
 
22
21
  class MetaType(str, Enum):
@@ -35,13 +34,13 @@ class ConfigFile(BaseModel):
35
34
  See https://github.com/openapi-generators/openapi-python-client#configuration
36
35
  """
37
36
 
38
- class_overrides: Optional[dict[str, ClassOverride]] = None
39
- content_type_overrides: Optional[dict[str, str]] = None
40
- project_name_override: Optional[str] = None
41
- package_name_override: Optional[str] = None
42
- package_version_override: Optional[str] = None
37
+ class_overrides: dict[str, ClassOverride] | None = None
38
+ content_type_overrides: dict[str, str] | None = None
39
+ project_name_override: str | None = None
40
+ package_name_override: str | None = None
41
+ package_version_override: str | None = None
43
42
  use_path_prefixes_for_title_model_names: bool = True
44
- post_hooks: Optional[list[str]] = None
43
+ post_hooks: list[str] | None = None
45
44
  docstrings_on_attributes: bool = False
46
45
  field_prefix: str = "field_"
47
46
  generate_all_tags: bool = False
@@ -67,9 +66,9 @@ class Config:
67
66
 
68
67
  meta_type: MetaType
69
68
  class_overrides: dict[str, ClassOverride]
70
- project_name_override: Optional[str]
71
- package_name_override: Optional[str]
72
- package_version_override: Optional[str]
69
+ project_name_override: str | None
70
+ package_name_override: str | None
71
+ package_version_override: str | None
73
72
  use_path_prefixes_for_title_model_names: bool
74
73
  post_hooks: list[str]
75
74
  docstrings_on_attributes: bool
@@ -77,31 +76,31 @@ class Config:
77
76
  generate_all_tags: bool
78
77
  http_timeout: int
79
78
  literal_enums: bool
80
- document_source: Union[Path, str]
79
+ document_source: Path | str
81
80
  file_encoding: str
82
81
  content_type_overrides: dict[str, str]
83
82
  overwrite: bool
84
- output_path: Optional[Path]
83
+ output_path: Path | None
85
84
 
86
85
  @staticmethod
87
86
  def from_sources(
88
87
  config_file: ConfigFile,
89
88
  meta_type: MetaType,
90
- document_source: Union[Path, str],
89
+ document_source: Path | str,
91
90
  file_encoding: str,
92
91
  overwrite: bool,
93
- output_path: Optional[Path],
92
+ output_path: Path | None,
94
93
  ) -> "Config":
95
94
  if config_file.post_hooks is not None:
96
95
  post_hooks = config_file.post_hooks
97
96
  elif meta_type == MetaType.NONE:
98
97
  post_hooks = [
99
- "ruff check . --fix --extend-select=I",
98
+ "ruff check . --fix-only --extend-select=I",
100
99
  "ruff format .",
101
100
  ]
102
101
  else:
103
102
  post_hooks = [
104
- "ruff check --fix .",
103
+ "ruff check --fix-only .",
105
104
  "ruff format .",
106
105
  ]
107
106
 
@@ -1,5 +1,4 @@
1
1
  import sys
2
- from typing import Union
3
2
 
4
3
  import attr
5
4
 
@@ -45,10 +44,10 @@ def body_from_data(
45
44
  *,
46
45
  data: oai.Operation,
47
46
  schemas: Schemas,
48
- request_bodies: dict[str, Union[oai.RequestBody, oai.Reference]],
47
+ request_bodies: dict[str, oai.RequestBody | oai.Reference],
49
48
  config: Config,
50
49
  endpoint_name: str,
51
- ) -> tuple[list[Union[Body, ParseError]], Schemas]:
50
+ ) -> tuple[list[Body | ParseError], Schemas]:
52
51
  """Adds form or JSON body to Endpoint if included in data"""
53
52
  body = _resolve_reference(data.request_body, request_bodies)
54
53
  if isinstance(body, ParseError):
@@ -56,7 +55,7 @@ def body_from_data(
56
55
  if body is None:
57
56
  return [], schemas
58
57
 
59
- bodies: list[Union[Body, ParseError]] = []
58
+ bodies: list[Body | ParseError] = []
60
59
  body_content = body.content
61
60
  prefix_type_names = len(body_content) > 1
62
61
 
@@ -132,8 +131,8 @@ def body_from_data(
132
131
 
133
132
 
134
133
  def _resolve_reference(
135
- body: Union[oai.RequestBody, oai.Reference, None], request_bodies: dict[str, Union[oai.RequestBody, oai.Reference]]
136
- ) -> Union[oai.RequestBody, ParseError, None]:
134
+ body: oai.RequestBody | oai.Reference | None, request_bodies: dict[str, oai.RequestBody | oai.Reference]
135
+ ) -> oai.RequestBody | ParseError | None:
137
136
  if body is None:
138
137
  return None
139
138
  references_seen = []
@@ -1,6 +1,5 @@
1
1
  from dataclasses import dataclass
2
2
  from enum import Enum
3
- from typing import Optional
4
3
 
5
4
  __all__ = ["ErrorLevel", "GeneratorError", "ParameterError", "ParseError", "PropertyError"]
6
5
 
@@ -18,7 +17,7 @@ class ErrorLevel(Enum):
18
17
  class GeneratorError:
19
18
  """Base data struct containing info on an error that occurred"""
20
19
 
21
- detail: Optional[str] = None
20
+ detail: str | None = None
22
21
  level: ErrorLevel = ErrorLevel.ERROR
23
22
  header: str = "Unable to generate the client"
24
23
 
@@ -28,7 +27,7 @@ class ParseError(GeneratorError):
28
27
  """An error raised when there's a problem parsing an OpenAPI document"""
29
28
 
30
29
  level: ErrorLevel = ErrorLevel.WARNING
31
- data: Optional[BaseModel] = None
30
+ data: BaseModel | None = None
32
31
  header: str = "Unable to parse this part of your OpenAPI document: "
33
32
 
34
33
 
@@ -2,7 +2,7 @@ import re
2
2
  from collections.abc import Iterator
3
3
  from copy import deepcopy
4
4
  from dataclasses import dataclass, field
5
- from typing import Any, Optional, Protocol, Union
5
+ from typing import Any, Protocol
6
6
 
7
7
  from pydantic import ValidationError
8
8
 
@@ -49,8 +49,8 @@ class EndpointCollection:
49
49
  data: dict[str, oai.PathItem],
50
50
  schemas: Schemas,
51
51
  parameters: Parameters,
52
- request_bodies: dict[str, Union[oai.RequestBody, oai.Reference]],
53
- responses: dict[str, Union[oai.Response, oai.Reference]],
52
+ request_bodies: dict[str, oai.RequestBody | oai.Reference],
53
+ responses: dict[str, oai.Response | oai.Reference],
54
54
  config: Config,
55
55
  ) -> tuple[dict[utils.PythonIdentifier, "EndpointCollection"], Schemas, Parameters]:
56
56
  """Parse the openapi paths data to get EndpointCollections by tag"""
@@ -60,7 +60,7 @@ class EndpointCollection:
60
60
 
61
61
  for path, path_data in data.items():
62
62
  for method in methods:
63
- operation: Optional[oai.Operation] = getattr(path_data, method)
63
+ operation: oai.Operation | None = getattr(path_data, method)
64
64
  if operation is None:
65
65
  continue
66
66
 
@@ -125,7 +125,7 @@ class RequestBodyParser(Protocol):
125
125
 
126
126
  def __call__(
127
127
  self, *, body: oai.RequestBody, schemas: Schemas, parent_name: str, config: Config
128
- ) -> tuple[Union[Property, PropertyError, None], Schemas]: ... # pragma: no cover
128
+ ) -> tuple[Property | PropertyError | None, Schemas]: ... # pragma: no cover
129
129
 
130
130
 
131
131
  @dataclass
@@ -136,11 +136,11 @@ class Endpoint:
136
136
 
137
137
  path: str
138
138
  method: str
139
- description: Optional[str]
139
+ description: str | None
140
140
  name: str
141
141
  requires_security: bool
142
142
  tags: list[PythonIdentifier]
143
- summary: Optional[str] = ""
143
+ summary: str | None = ""
144
144
  relative_imports: set[str] = field(default_factory=set)
145
145
  query_parameters: list[Property] = field(default_factory=list)
146
146
  path_parameters: list[Property] = field(default_factory=list)
@@ -156,7 +156,7 @@ class Endpoint:
156
156
  endpoint: "Endpoint",
157
157
  data: oai.Responses,
158
158
  schemas: Schemas,
159
- responses: dict[str, Union[oai.Response, oai.Reference]],
159
+ responses: dict[str, oai.Response | oai.Reference],
160
160
  config: Config,
161
161
  ) -> tuple["Endpoint", Schemas]:
162
162
  endpoint = deepcopy(endpoint)
@@ -201,11 +201,11 @@ class Endpoint:
201
201
  def add_parameters(
202
202
  *,
203
203
  endpoint: "Endpoint",
204
- data: Union[oai.Operation, oai.PathItem],
204
+ data: oai.Operation | oai.PathItem,
205
205
  schemas: Schemas,
206
206
  parameters: Parameters,
207
207
  config: Config,
208
- ) -> tuple[Union["Endpoint", ParseError], Schemas, Parameters]:
208
+ ) -> tuple["Endpoint | ParseError", Schemas, Parameters]:
209
209
  """Process the defined `parameters` for an Endpoint.
210
210
 
211
211
  Any existing parameters will be ignored, so earlier instances of a parameter take precedence. PathItem
@@ -312,8 +312,8 @@ class Endpoint:
312
312
  self,
313
313
  *,
314
314
  config: Config,
315
- previously_modified_params: Optional[set[tuple[oai.ParameterLocation, str]]] = None,
316
- ) -> Union["Endpoint", ParseError]:
315
+ previously_modified_params: set[tuple[oai.ParameterLocation, str]] | None = None,
316
+ ) -> "Endpoint | ParseError":
317
317
  """Check for conflicting parameters
318
318
 
319
319
  For parameters that have the same python_name but are in different locations, append the location to the
@@ -366,7 +366,7 @@ class Endpoint:
366
366
  return self
367
367
 
368
368
  @staticmethod
369
- def sort_parameters(*, endpoint: "Endpoint") -> Union["Endpoint", ParseError]:
369
+ def sort_parameters(*, endpoint: "Endpoint") -> "Endpoint | ParseError":
370
370
  """
371
371
  Sorts the path parameters of an `endpoint` so that they match the order declared in `endpoint.path`.
372
372
 
@@ -403,10 +403,10 @@ class Endpoint:
403
403
  tags: list[PythonIdentifier],
404
404
  schemas: Schemas,
405
405
  parameters: Parameters,
406
- request_bodies: dict[str, Union[oai.RequestBody, oai.Reference]],
407
- responses: dict[str, Union[oai.Response, oai.Reference]],
406
+ request_bodies: dict[str, oai.RequestBody | oai.Reference],
407
+ responses: dict[str, oai.Response | oai.Reference],
408
408
  config: Config,
409
- ) -> tuple[Union["Endpoint", ParseError], Schemas, Parameters]:
409
+ ) -> tuple["Endpoint | ParseError", Schemas, Parameters]:
410
410
  """Construct an endpoint from the OpenAPI data"""
411
411
 
412
412
  if data.operationId is None:
@@ -469,12 +469,12 @@ class Endpoint:
469
469
 
470
470
  def response_type(self) -> str:
471
471
  """Get the Python type of any response from this endpoint"""
472
- types = sorted({response.prop.get_type_string(quoted=False) for response in self.responses})
472
+ types = sorted({response.prop.get_type_string() for response in self.responses})
473
473
  if len(types) == 0:
474
474
  return "Any"
475
475
  if len(types) == 1:
476
476
  return types[0]
477
- return f"Union[{', '.join(types)}]"
477
+ return " | ".join(types)
478
478
 
479
479
  def iter_all_parameters(self) -> Iterator[tuple[oai.ParameterLocation, Property]]:
480
480
  """Iterate through all the parameters of this endpoint"""
@@ -499,15 +499,15 @@ class GeneratorData:
499
499
  """All the data needed to generate a client"""
500
500
 
501
501
  title: str
502
- description: Optional[str]
502
+ description: str | None
503
503
  version: str
504
504
  models: list[ModelProperty]
505
505
  errors: list[ParseError]
506
506
  endpoint_collections_by_tag: dict[utils.PythonIdentifier, EndpointCollection]
507
- enums: list[Union[EnumProperty, LiteralEnumProperty]]
507
+ enums: list[EnumProperty | LiteralEnumProperty]
508
508
 
509
509
  @staticmethod
510
- def from_dict(data: dict[str, Any], *, config: Config) -> Union["GeneratorData", GeneratorError]:
510
+ def from_dict(data: dict[str, Any], *, config: Config) -> "GeneratorData | GeneratorError":
511
511
  """Create an OpenAPI from dict"""
512
512
  try:
513
513
  openapi = oai.OpenAPI.model_validate(data)
@@ -540,7 +540,7 @@ class GeneratorData:
540
540
  )
541
541
 
542
542
  enums = [
543
- prop for prop in schemas.classes_by_name.values() if isinstance(prop, (EnumProperty, LiteralEnumProperty))
543
+ prop for prop in schemas.classes_by_name.values() if isinstance(prop, EnumProperty | LiteralEnumProperty)
544
544
  ]
545
545
  models = [prop for prop in schemas.classes_by_name.values() if isinstance(prop, ModelProperty)]
546
546
 
@@ -93,12 +93,10 @@ class ConstProperty(PropertyProtocol):
93
93
  self,
94
94
  no_optional: bool = False,
95
95
  json: bool = False,
96
- *,
97
- quoted: bool = False,
98
96
  ) -> str:
99
97
  lit = f"Literal[{self.value.python_code}]"
100
98
  if not no_optional and not self.required:
101
- return f"Union[{lit}, Unset]"
99
+ return f"{lit} | Unset"
102
100
  return lit
103
101
 
104
102
  def get_imports(self, *, prefix: str) -> set[str]:
@@ -112,6 +110,6 @@ class ConstProperty(PropertyProtocol):
112
110
  if self.required:
113
111
  return {"from typing import Literal, cast"}
114
112
  return {
115
- "from typing import Literal, Union, cast",
113
+ "from typing import Literal, cast",
116
114
  f"from {prefix}types import UNSET, Unset",
117
115
  }
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  __all__ = ["EnumProperty", "ValueType"]
4
4
 
5
- from typing import Any, ClassVar, Union, cast
5
+ from typing import Any, ClassVar, cast
6
6
 
7
7
  from attr import evolve
8
8
  from attrs import define
@@ -16,7 +16,7 @@ from .protocol import PropertyProtocol, Value
16
16
  from .schemas import Class, Schemas
17
17
  from .union import UnionProperty
18
18
 
19
- ValueType = Union[str, int]
19
+ ValueType = str | int
20
20
 
21
21
 
22
22
  @define
@@ -98,9 +98,7 @@ class EnumProperty(PropertyProtocol):
98
98
  value_type = next(iter(value_types))
99
99
  if value_type not in (str, int):
100
100
  return PropertyError(header=f"Unsupported enum type {value_type}", data=data), schemas
101
- value_list = cast(
102
- Union[list[int], list[str]], unchecked_value_list
103
- ) # We checked this with all the value_types stuff
101
+ value_list = cast(list[int] | list[str], unchecked_value_list) # We checked this with all the value_types stuff
104
102
 
105
103
  if len(value_list) < len(enum): # Only one of the values was None, that becomes a union
106
104
  data.oneOf = [
@@ -165,10 +163,10 @@ class EnumProperty(PropertyProtocol):
165
163
  return PropertyError(detail=f"Value {value} is not valid for enum {self.name}")
166
164
  return PropertyError(detail=f"Cannot convert {value} to enum {self.name} of type {self.value_type}")
167
165
 
168
- def get_base_type_string(self, *, quoted: bool = False) -> str:
166
+ def get_base_type_string(self) -> str:
169
167
  return self.class_info.name
170
168
 
171
- def get_base_json_type_string(self, *, quoted: bool = False) -> str:
169
+ def get_base_json_type_string(self) -> str:
172
170
  return self.value_type.__name__
173
171
 
174
172
  def get_imports(self, *, prefix: str) -> set[str]:
@@ -192,7 +190,7 @@ class EnumProperty(PropertyProtocol):
192
190
  use_var_names = len(var_names) == len(values)
193
191
 
194
192
  for i, value in enumerate(values):
195
- value = cast(Union[str, int], value)
193
+ value = cast(str | int, value)
196
194
  if isinstance(value, int):
197
195
  if use_var_names:
198
196
  key = var_names[i]
@@ -105,11 +105,11 @@ class ListProperty(PropertyProtocol):
105
105
  def convert_value(self, value: Any) -> Value | None | PropertyError:
106
106
  return None # pragma: no cover
107
107
 
108
- def get_base_type_string(self, *, quoted: bool = False) -> str:
109
- return f"list[{self.inner_property.get_type_string(quoted=not self.inner_property.is_base_type)}]"
108
+ def get_base_type_string(self) -> str:
109
+ return f"list[{self.inner_property.get_type_string()}]"
110
110
 
111
- def get_base_json_type_string(self, *, quoted: bool = False) -> str:
112
- return f"list[{self.inner_property.get_type_string(json=True, quoted=not self.inner_property.is_base_type)}]"
111
+ def get_base_json_type_string(self) -> str:
112
+ return f"list[{self.inner_property.get_type_string(json=True)}]"
113
113
 
114
114
  def get_instance_type_string(self) -> str:
115
115
  """Get a string representation of runtime type that should be used for `isinstance` checks"""
@@ -137,8 +137,6 @@ class ListProperty(PropertyProtocol):
137
137
  self,
138
138
  no_optional: bool = False,
139
139
  json: bool = False,
140
- *,
141
- quoted: bool = False,
142
140
  ) -> str:
143
141
  """
144
142
  Get a string representation of type that should be used when declaring this property
@@ -154,4 +152,4 @@ class ListProperty(PropertyProtocol):
154
152
 
155
153
  if no_optional or self.required:
156
154
  return type_string
157
- return f"Union[Unset, {type_string}]"
155
+ return f"{type_string} | Unset"
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  __all__ = ["LiteralEnumProperty"]
4
4
 
5
- from typing import Any, ClassVar, Union, cast
5
+ from typing import Any, ClassVar, cast
6
6
 
7
7
  from attr import evolve
8
8
  from attrs import define
@@ -16,7 +16,7 @@ from .protocol import PropertyProtocol, Value
16
16
  from .schemas import Class, Schemas
17
17
  from .union import UnionProperty
18
18
 
19
- ValueType = Union[str, int]
19
+ ValueType = str | int
20
20
 
21
21
 
22
22
  @define
@@ -97,9 +97,7 @@ class LiteralEnumProperty(PropertyProtocol):
97
97
  value_type = next(iter(value_types))
98
98
  if value_type not in (str, int):
99
99
  return PropertyError(header=f"Unsupported enum type {value_type}", data=data), schemas
100
- value_list = cast(
101
- Union[list[int], list[str]], unchecked_value_list
102
- ) # We checked this with all the value_types stuff
100
+ value_list = cast(list[int] | list[str], unchecked_value_list) # We checked this with all the value_types stuff
103
101
 
104
102
  if len(value_list) < len(enum): # Only one of the values was None, that becomes a union
105
103
  data.oneOf = [
@@ -162,10 +160,10 @@ class LiteralEnumProperty(PropertyProtocol):
162
160
  return PropertyError(detail=f"Value {value} is not valid for enum {self.name}")
163
161
  return PropertyError(detail=f"Cannot convert {value} to enum {self.name} of type {self.value_type}")
164
162
 
165
- def get_base_type_string(self, *, quoted: bool = False) -> str:
163
+ def get_base_type_string(self) -> str:
166
164
  return self.class_info.name
167
165
 
168
- def get_base_json_type_string(self, *, quoted: bool = False) -> str:
166
+ def get_base_json_type_string(self) -> str:
169
167
  return self.value_type.__name__
170
168
 
171
169
  def get_instance_type_string(self) -> str:
@@ -105,9 +105,9 @@ def _merge_string_with_format(prop1: Property, prop2: Property) -> Property | No
105
105
 
106
106
  def _merge_numeric(prop1: Property, prop2: Property) -> IntProperty | None | PropertyError:
107
107
  """Merge IntProperty with FloatProperty"""
108
- if isinstance(prop1, IntProperty) and isinstance(prop2, (IntProperty, FloatProperty)):
108
+ if isinstance(prop1, IntProperty) and isinstance(prop2, IntProperty | FloatProperty):
109
109
  return _merge_common_attributes(prop1, prop2)
110
- elif isinstance(prop2, IntProperty) and isinstance(prop1, (IntProperty, FloatProperty)):
110
+ elif isinstance(prop2, IntProperty) and isinstance(prop1, IntProperty | FloatProperty):
111
111
  # Use the IntProperty as a base since it's more restrictive, but keep the correct override order
112
112
  return _merge_common_attributes(prop2, prop1, prop2)
113
113
  else: