openapi-python-client 0.22.0__tar.gz → 0.23.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 (110) hide show
  1. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/PKG-INFO +17 -6
  2. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/README.md +10 -0
  3. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/__init__.py +5 -5
  4. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/cli.py +2 -2
  5. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/config.py +3 -0
  6. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/parser/openapi.py +19 -13
  7. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/__init__.py +11 -0
  8. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/components.py +2 -0
  9. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/encoding.py +3 -3
  10. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/header.py +2 -0
  11. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/media_type.py +2 -0
  12. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/open_api.py +5 -7
  13. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/operation.py +2 -8
  14. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/parameter.py +2 -0
  15. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/path_item.py +6 -7
  16. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/request_body.py +2 -0
  17. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/response.py +2 -0
  18. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/schema.py +1 -4
  19. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/pyproject.toml.jinja +4 -4
  20. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/setup.py.jinja +1 -1
  21. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/pyproject.toml +10 -10
  22. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/.gitignore +0 -0
  23. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/LICENSE +0 -0
  24. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/__main__.py +0 -0
  25. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/parser/__init__.py +0 -0
  26. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/parser/bodies.py +0 -0
  27. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/parser/errors.py +0 -0
  28. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/parser/properties/__init__.py +0 -0
  29. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/parser/properties/any.py +0 -0
  30. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/parser/properties/boolean.py +0 -0
  31. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/parser/properties/const.py +0 -0
  32. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/parser/properties/date.py +0 -0
  33. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/parser/properties/datetime.py +0 -0
  34. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/parser/properties/enum_property.py +0 -0
  35. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/parser/properties/file.py +0 -0
  36. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/parser/properties/float.py +0 -0
  37. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/parser/properties/int.py +0 -0
  38. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/parser/properties/list_property.py +0 -0
  39. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/parser/properties/literal_enum_property.py +0 -0
  40. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/parser/properties/merge_properties.py +0 -0
  41. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/parser/properties/model_property.py +0 -0
  42. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/parser/properties/none.py +0 -0
  43. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/parser/properties/property.py +0 -0
  44. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/parser/properties/protocol.py +0 -0
  45. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/parser/properties/schemas.py +0 -0
  46. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/parser/properties/string.py +0 -0
  47. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/parser/properties/union.py +0 -0
  48. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/parser/properties/uuid.py +0 -0
  49. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/parser/responses.py +0 -0
  50. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/py.typed +0 -0
  51. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/3.0.3.md +0 -0
  52. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/3.1.0.md +0 -0
  53. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/__init__.py +0 -0
  54. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/data_type.py +0 -0
  55. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/LICENSE +0 -0
  56. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/README.md +0 -0
  57. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/callback.py +0 -0
  58. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/contact.py +0 -0
  59. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/discriminator.py +0 -0
  60. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/example.py +0 -0
  61. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/external_documentation.py +0 -0
  62. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/info.py +0 -0
  63. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/license.py +0 -0
  64. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/link.py +0 -0
  65. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/oauth_flow.py +0 -0
  66. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/oauth_flows.py +0 -0
  67. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/paths.py +0 -0
  68. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/reference.py +0 -0
  69. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/responses.py +0 -0
  70. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/security_requirement.py +0 -0
  71. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/security_scheme.py +0 -0
  72. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/server.py +0 -0
  73. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/server_variable.py +0 -0
  74. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/tag.py +0 -0
  75. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/openapi_schema_pydantic/xml.py +0 -0
  76. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/schema/parameter_location.py +0 -0
  77. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/.gitignore.jinja +0 -0
  78. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/README.md.jinja +0 -0
  79. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/api_init.py.jinja +0 -0
  80. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/client.py.jinja +0 -0
  81. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/endpoint_init.py.jinja +0 -0
  82. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/endpoint_macros.py.jinja +0 -0
  83. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/endpoint_module.py.jinja +0 -0
  84. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/errors.py.jinja +0 -0
  85. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/helpers.jinja +0 -0
  86. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/int_enum.py.jinja +0 -0
  87. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/literal_enum.py.jinja +0 -0
  88. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/model.py.jinja +0 -0
  89. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/models_init.py.jinja +0 -0
  90. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/package_init.py.jinja +0 -0
  91. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/property_templates/any_property.py.jinja +0 -0
  92. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/property_templates/boolean_property.py.jinja +0 -0
  93. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/property_templates/const_property.py.jinja +0 -0
  94. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/property_templates/date_property.py.jinja +0 -0
  95. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/property_templates/datetime_property.py.jinja +0 -0
  96. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/property_templates/enum_property.py.jinja +0 -0
  97. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/property_templates/file_property.py.jinja +0 -0
  98. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/property_templates/float_property.py.jinja +0 -0
  99. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/property_templates/helpers.jinja +0 -0
  100. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/property_templates/int_property.py.jinja +0 -0
  101. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/property_templates/list_property.py.jinja +0 -0
  102. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/property_templates/literal_enum_property.py.jinja +0 -0
  103. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/property_templates/model_property.py.jinja +0 -0
  104. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/property_templates/property_macros.py.jinja +0 -0
  105. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/property_templates/union_property.py.jinja +0 -0
  106. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/property_templates/uuid_property.py.jinja +0 -0
  107. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/pyproject_ruff.toml.jinja +0 -0
  108. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/str_enum.py.jinja +0 -0
  109. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/templates/types.py.jinja +0 -0
  110. {openapi_python_client-0.22.0 → openapi_python_client-0.23.1}/openapi_python_client/utils.py +0 -0
@@ -1,10 +1,11 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: openapi-python-client
3
- Version: 0.22.0
3
+ Version: 0.23.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>
7
7
  License: MIT
8
+ License-File: LICENSE
8
9
  Keywords: Client,Generator,OpenAPI
9
10
  Classifier: Development Status :: 4 - Beta
10
11
  Classifier: Intended Audience :: Developers
@@ -18,16 +19,16 @@ Classifier: Programming Language :: Python :: 3.13
18
19
  Classifier: Topic :: Software Development :: Code Generators
19
20
  Classifier: Typing :: Typed
20
21
  Requires-Python: <4.0,>=3.9
21
- Requires-Dist: attrs>=21.3.0
22
+ Requires-Dist: attrs>=22.2.0
22
23
  Requires-Dist: colorama>=0.4.3; sys_platform == 'win32'
23
- Requires-Dist: httpx<0.28.0,>=0.20.0
24
+ Requires-Dist: httpx<0.29.0,>=0.20.0
24
25
  Requires-Dist: jinja2<4.0.0,>=3.0.0
25
26
  Requires-Dist: pydantic<3.0.0,>=2.1.1
26
27
  Requires-Dist: python-dateutil<3.0.0,>=2.8.1
27
28
  Requires-Dist: ruamel-yaml<0.19.0,>=0.18.6
28
- Requires-Dist: ruff<0.9,>=0.2
29
+ Requires-Dist: ruff<0.10,>=0.2
29
30
  Requires-Dist: shellingham<2.0.0,>=1.3.2
30
- Requires-Dist: typer<0.14,>0.6
31
+ Requires-Dist: typer<0.16,>0.6
31
32
  Requires-Dist: typing-extensions<5.0.0,>=4.8.0
32
33
  Description-Content-Type: text/markdown
33
34
 
@@ -141,6 +142,16 @@ literal_enums: true
141
142
 
142
143
  This is especially useful if enum values, when transformed to their Python names, end up conflicting due to case sensitivity or special symbols.
143
144
 
145
+ ### generate_all_tags
146
+
147
+ `openapi-python-client` generates module names within the `api` module based on the OpenAPI `tags` of each endpoint.
148
+ By default, only the _first_ tag is generated. If you want to generate **duplicate** endpoint functions using _every_ tag
149
+ listed, you can enable this option:
150
+
151
+ ```yaml
152
+ generate_all_tags: true
153
+ ```
154
+
144
155
  ### project_name_override and package_name_override
145
156
 
146
157
  Used to change the name of generated client library project/package. If the project name is changed but an override for the package name
@@ -108,6 +108,16 @@ literal_enums: true
108
108
 
109
109
  This is especially useful if enum values, when transformed to their Python names, end up conflicting due to case sensitivity or special symbols.
110
110
 
111
+ ### generate_all_tags
112
+
113
+ `openapi-python-client` generates module names within the `api` module based on the OpenAPI `tags` of each endpoint.
114
+ By default, only the _first_ tag is generated. If you want to generate **duplicate** endpoint functions using _every_ tag
115
+ listed, you can enable this option:
116
+
117
+ ```yaml
118
+ generate_all_tags: true
119
+ ```
120
+
111
121
  ### project_name_override and package_name_override
112
122
 
113
123
  Used to change the name of generated client library project/package. If the project name is changed but an override for the package name
@@ -108,13 +108,11 @@ class Project:
108
108
  """Create the project from templates"""
109
109
 
110
110
  print(f"Generating {self.project_dir}")
111
- if self.config.overwrite:
112
- shutil.rmtree(self.project_dir, ignore_errors=True)
113
-
114
111
  try:
115
112
  self.project_dir.mkdir()
116
113
  except FileExistsError:
117
- return [GeneratorError(detail="Directory already exists. Delete it or use the --overwrite option.")]
114
+ if not self.config.overwrite:
115
+ return [GeneratorError(detail="Directory already exists. Delete it or use the --overwrite option.")]
118
116
  self._create_package()
119
117
  self._build_metadata()
120
118
  self._build_models()
@@ -158,7 +156,7 @@ class Project:
158
156
 
159
157
  def _create_package(self) -> None:
160
158
  if self.package_dir != self.project_dir:
161
- self.package_dir.mkdir()
159
+ self.package_dir.mkdir(exist_ok=True)
162
160
  # Package __init__.py
163
161
  package_init = self.package_dir / "__init__.py"
164
162
 
@@ -214,6 +212,7 @@ class Project:
214
212
  def _build_models(self) -> None:
215
213
  # Generate models
216
214
  models_dir = self.package_dir / "models"
215
+ shutil.rmtree(models_dir, ignore_errors=True)
217
216
  models_dir.mkdir()
218
217
  models_init = models_dir / "__init__.py"
219
218
  imports = []
@@ -259,6 +258,7 @@ class Project:
259
258
 
260
259
  # Generate endpoints
261
260
  api_dir = self.package_dir / "api"
261
+ shutil.rmtree(api_dir, ignore_errors=True)
262
262
  api_dir.mkdir()
263
263
  api_init_path = api_dir / "__init__.py"
264
264
  api_init_template = self.env.get_template("api_init.py.jinja")
@@ -10,7 +10,7 @@ from openapi_python_client import MetaType
10
10
  from openapi_python_client.config import Config, ConfigFile
11
11
  from openapi_python_client.parser.errors import ErrorLevel, GeneratorError, ParseError
12
12
 
13
- app = typer.Typer()
13
+ app = typer.Typer(name="openapi-python-client")
14
14
 
15
15
 
16
16
  def _version_callback(value: bool) -> None:
@@ -63,7 +63,7 @@ def _process_config(
63
63
  # noinspection PyUnusedLocal
64
64
 
65
65
 
66
- @app.callback(name="openapi-python-client")
66
+ @app.callback()
67
67
  def cli(
68
68
  version: bool = typer.Option(False, "--version", callback=_version_callback, help="Print the version and exit"),
69
69
  ) -> None:
@@ -42,6 +42,7 @@ class ConfigFile(BaseModel):
42
42
  use_path_prefixes_for_title_model_names: bool = True
43
43
  post_hooks: Optional[list[str]] = None
44
44
  field_prefix: str = "field_"
45
+ generate_all_tags: bool = False
45
46
  http_timeout: int = 5
46
47
  literal_enums: bool = False
47
48
 
@@ -70,6 +71,7 @@ class Config:
70
71
  use_path_prefixes_for_title_model_names: bool
71
72
  post_hooks: list[str]
72
73
  field_prefix: str
74
+ generate_all_tags: bool
73
75
  http_timeout: int
74
76
  literal_enums: bool
75
77
  document_source: Union[Path, str]
@@ -110,6 +112,7 @@ class Config:
110
112
  use_path_prefixes_for_title_model_names=config_file.use_path_prefixes_for_title_model_names,
111
113
  post_hooks=post_hooks,
112
114
  field_prefix=config_file.field_prefix,
115
+ generate_all_tags=config_file.generate_all_tags,
113
116
  http_timeout=config_file.http_timeout,
114
117
  literal_enums=config_file.literal_enums,
115
118
  document_source=document_source,
@@ -63,13 +63,18 @@ class EndpointCollection:
63
63
  operation: Optional[oai.Operation] = getattr(path_data, method)
64
64
  if operation is None:
65
65
  continue
66
- tag = utils.PythonIdentifier(value=(operation.tags or ["default"])[0], prefix="tag")
67
- collection = endpoints_by_tag.setdefault(tag, EndpointCollection(tag=tag))
66
+
67
+ tags = [utils.PythonIdentifier(value=tag, prefix="tag") for tag in operation.tags or ["default"]]
68
+ if not config.generate_all_tags:
69
+ tags = tags[:1]
70
+
71
+ collections = [endpoints_by_tag.setdefault(tag, EndpointCollection(tag=tag)) for tag in tags]
72
+
68
73
  endpoint, schemas, parameters = Endpoint.from_data(
69
74
  data=operation,
70
75
  path=path,
71
76
  method=method,
72
- tag=tag,
77
+ tags=tags,
73
78
  schemas=schemas,
74
79
  parameters=parameters,
75
80
  request_bodies=request_bodies,
@@ -87,15 +92,16 @@ class EndpointCollection:
87
92
  if not isinstance(endpoint, ParseError):
88
93
  endpoint = Endpoint.sort_parameters(endpoint=endpoint)
89
94
  if isinstance(endpoint, ParseError):
90
- endpoint.header = (
91
- f"WARNING parsing {method.upper()} {path} within {tag}. Endpoint will not be generated."
92
- )
93
- collection.parse_errors.append(endpoint)
95
+ endpoint.header = f"WARNING parsing {method.upper()} {path} within {'/'.join(tags)}. Endpoint will not be generated."
96
+ for collection in collections:
97
+ collection.parse_errors.append(endpoint)
94
98
  continue
95
99
  for error in endpoint.errors:
96
- error.header = f"WARNING parsing {method.upper()} {path} within {tag}."
97
- collection.parse_errors.append(error)
98
- collection.endpoints.append(endpoint)
100
+ error.header = f"WARNING parsing {method.upper()} {path} within {'/'.join(tags)}."
101
+ for collection in collections:
102
+ collection.parse_errors.append(error)
103
+ for collection in collections:
104
+ collection.endpoints.append(endpoint)
99
105
 
100
106
  return endpoints_by_tag, schemas, parameters
101
107
 
@@ -132,7 +138,7 @@ class Endpoint:
132
138
  description: Optional[str]
133
139
  name: str
134
140
  requires_security: bool
135
- tag: str
141
+ tags: list[PythonIdentifier]
136
142
  summary: Optional[str] = ""
137
143
  relative_imports: set[str] = field(default_factory=set)
138
144
  query_parameters: list[Property] = field(default_factory=list)
@@ -393,7 +399,7 @@ class Endpoint:
393
399
  data: oai.Operation,
394
400
  path: str,
395
401
  method: str,
396
- tag: str,
402
+ tags: list[PythonIdentifier],
397
403
  schemas: Schemas,
398
404
  parameters: Parameters,
399
405
  request_bodies: dict[str, Union[oai.RequestBody, oai.Reference]],
@@ -413,7 +419,7 @@ class Endpoint:
413
419
  description=utils.remove_string_escapes(data.description) if data.description else "",
414
420
  name=name,
415
421
  requires_security=bool(data.security),
416
- tag=tag,
422
+ tags=tags,
417
423
  )
418
424
 
419
425
  result, schemas, parameters = Endpoint.add_parameters(
@@ -70,3 +70,14 @@ from .server import Server
70
70
  from .server_variable import ServerVariable
71
71
  from .tag import Tag
72
72
  from .xml import XML
73
+
74
+ PathItem.model_rebuild()
75
+ Operation.model_rebuild()
76
+ Components.model_rebuild()
77
+ Encoding.model_rebuild()
78
+ MediaType.model_rebuild()
79
+ OpenAPI.model_rebuild()
80
+ Parameter.model_rebuild()
81
+ Header.model_rebuild()
82
+ RequestBody.model_rebuild()
83
+ Response.model_rebuild()
@@ -35,6 +35,8 @@ class Components(BaseModel):
35
35
  links: Optional[dict[str, Union[Link, Reference]]] = None
36
36
  callbacks: Optional[dict[str, Union[Callback, Reference]]] = None
37
37
  model_config = ConfigDict(
38
+ # `Callback` contains an unresolvable forward reference, will rebuild in `__init__.py`:
39
+ defer_build=True,
38
40
  extra="allow",
39
41
  json_schema_extra={
40
42
  "examples": [
@@ -6,8 +6,6 @@ from .reference import Reference
6
6
 
7
7
  if TYPE_CHECKING: # pragma: no cover
8
8
  from .header import Header
9
- else:
10
- Header = "Header"
11
9
 
12
10
 
13
11
  class Encoding(BaseModel):
@@ -19,11 +17,13 @@ class Encoding(BaseModel):
19
17
  """
20
18
 
21
19
  contentType: Optional[str] = None
22
- headers: Optional[dict[str, Union[Header, Reference]]] = None
20
+ headers: Optional[dict[str, Union["Header", Reference]]] = None
23
21
  style: Optional[str] = None
24
22
  explode: bool = False
25
23
  allowReserved: bool = False
26
24
  model_config = ConfigDict(
25
+ # `Header` is an unresolvable forward reference, will rebuild in `__init__.py`:
26
+ defer_build=True,
27
27
  extra="allow",
28
28
  json_schema_extra={
29
29
  "examples": [
@@ -21,6 +21,8 @@ class Header(Parameter):
21
21
  name: str = Field(default="")
22
22
  param_in: ParameterLocation = Field(default=ParameterLocation.HEADER, alias="in")
23
23
  model_config = ConfigDict(
24
+ # `Parameter` is not build yet, will rebuild in `__init__.py`:
25
+ defer_build=True,
24
26
  extra="allow",
25
27
  populate_by_name=True,
26
28
  json_schema_extra={
@@ -21,6 +21,8 @@ class MediaType(BaseModel):
21
21
  examples: Optional[dict[str, Union[Example, Reference]]] = None
22
22
  encoding: Optional[dict[str, Encoding]] = None
23
23
  model_config = ConfigDict(
24
+ # `Encoding` is not build yet, will rebuild in `__init__.py`:
25
+ defer_build=True,
24
26
  extra="allow",
25
27
  populate_by_name=True,
26
28
  json_schema_extra={
@@ -5,9 +5,6 @@ from pydantic import BaseModel, ConfigDict, field_validator
5
5
  from .components import Components
6
6
  from .external_documentation import ExternalDocumentation
7
7
  from .info import Info
8
-
9
- # Required to update forward ref after object creation
10
- from .path_item import PathItem # noqa: F401
11
8
  from .paths import Paths
12
9
  from .security_requirement import SecurityRequirement
13
10
  from .server import Server
@@ -32,7 +29,11 @@ class OpenAPI(BaseModel):
32
29
  tags: Optional[list[Tag]] = None
33
30
  externalDocs: Optional[ExternalDocumentation] = None
34
31
  openapi: str
35
- model_config = ConfigDict(extra="allow")
32
+ model_config = ConfigDict(
33
+ # `Components` is not build yet, will rebuild in `__init__.py`:
34
+ defer_build=True,
35
+ extra="allow",
36
+ )
36
37
 
37
38
  @field_validator("openapi")
38
39
  @classmethod
@@ -46,6 +47,3 @@ class OpenAPI(BaseModel):
46
47
  if int(parts[1]) > 1:
47
48
  raise ValueError(f"Only OpenAPI versions 3.1.* are supported, got {value}")
48
49
  return value
49
-
50
-
51
- OpenAPI.model_rebuild()
@@ -4,11 +4,7 @@ from pydantic import BaseModel, ConfigDict, Field
4
4
 
5
5
  from .callback import Callback
6
6
  from .external_documentation import ExternalDocumentation
7
- from .header import Header # noqa: F401
8
7
  from .parameter import Parameter
9
-
10
- # Required to update forward ref after object creation, as this is not imported yet
11
- from .path_item import PathItem # noqa: F401
12
8
  from .reference import Reference
13
9
  from .request_body import RequestBody
14
10
  from .responses import Responses
@@ -38,6 +34,8 @@ class Operation(BaseModel):
38
34
  security: Optional[list[SecurityRequirement]] = None
39
35
  servers: Optional[list[Server]] = None
40
36
  model_config = ConfigDict(
37
+ # `Callback` contains an unresolvable forward reference, will rebuild in `__init__.py`:
38
+ defer_build=True,
41
39
  extra="allow",
42
40
  json_schema_extra={
43
41
  "examples": [
@@ -89,7 +87,3 @@ class Operation(BaseModel):
89
87
  ]
90
88
  },
91
89
  )
92
-
93
-
94
- # PathItem in Callback uses Operation, so we need to update forward refs due to circular dependency
95
- Operation.model_rebuild()
@@ -35,6 +35,8 @@ class Parameter(BaseModel):
35
35
  examples: Optional[dict[str, Union[Example, Reference]]] = None
36
36
  content: Optional[dict[str, MediaType]] = None
37
37
  model_config = ConfigDict(
38
+ # `MediaType` is not build yet, will rebuild in `__init__.py`:
39
+ defer_build=True,
38
40
  extra="allow",
39
41
  populate_by_name=True,
40
42
  json_schema_extra={
@@ -1,4 +1,4 @@
1
- from typing import Optional, Union
1
+ from typing import TYPE_CHECKING, Optional, Union
2
2
 
3
3
  from pydantic import BaseModel, ConfigDict, Field
4
4
 
@@ -6,6 +6,9 @@ from .parameter import Parameter
6
6
  from .reference import Reference
7
7
  from .server import Server
8
8
 
9
+ if TYPE_CHECKING:
10
+ from .operation import Operation # pragma: no cover
11
+
9
12
 
10
13
  class PathItem(BaseModel):
11
14
  """
@@ -33,6 +36,8 @@ class PathItem(BaseModel):
33
36
  servers: Optional[list[Server]] = None
34
37
  parameters: Optional[list[Union[Parameter, Reference]]] = None
35
38
  model_config = ConfigDict(
39
+ # `Operation` is an unresolvable forward reference, will rebuild in `__init__.py`:
40
+ defer_build=True,
36
41
  extra="allow",
37
42
  populate_by_name=True,
38
43
  json_schema_extra={
@@ -69,9 +74,3 @@ class PathItem(BaseModel):
69
74
  ]
70
75
  },
71
76
  )
72
-
73
-
74
- # Operation uses PathItem via Callback, so we need late import and to update forward refs due to circular dependency
75
- from .operation import Operation # noqa: E402
76
-
77
- PathItem.model_rebuild()
@@ -17,6 +17,8 @@ class RequestBody(BaseModel):
17
17
  content: dict[str, MediaType]
18
18
  required: bool = False
19
19
  model_config = ConfigDict(
20
+ # `MediaType` is not build yet, will rebuild in `__init__.py`:
21
+ defer_build=True,
20
22
  extra="allow",
21
23
  json_schema_extra={
22
24
  "examples": [
@@ -23,6 +23,8 @@ class Response(BaseModel):
23
23
  content: Optional[dict[str, MediaType]] = None
24
24
  links: Optional[dict[str, Union[Link, Reference]]] = None
25
25
  model_config = ConfigDict(
26
+ # `MediaType` is not build yet, will rebuild in `__init__.py`:
27
+ defer_build=True,
26
28
  extra="allow",
27
29
  json_schema_extra={
28
30
  "examples": [
@@ -43,7 +43,7 @@ class Schema(BaseModel):
43
43
  anyOf: list[Union[Reference, "Schema"]] = Field(default_factory=list)
44
44
  schema_not: Optional[Union[Reference, "Schema"]] = Field(default=None, alias="not")
45
45
  items: Optional[Union[Reference, "Schema"]] = None
46
- prefixItems: Optional[list[Union[Reference, "Schema"]]] = Field(default_factory=list)
46
+ prefixItems: list[Union[Reference, "Schema"]] = Field(default_factory=list)
47
47
  properties: Optional[dict[str, Union[Reference, "Schema"]]] = None
48
48
  additionalProperties: Optional[Union[bool, Reference, "Schema"]] = None
49
49
  description: Optional[str] = None
@@ -206,6 +206,3 @@ class Schema(BaseModel):
206
206
  self.oneOf = [Schema(type=DataType.NULL), Schema(allOf=self.allOf)]
207
207
  self.allOf = []
208
208
  return self
209
-
210
-
211
- Schema.model_rebuild()
@@ -19,8 +19,8 @@ include = ["CHANGELOG.md", "{{ package_name }}/py.typed"]
19
19
 
20
20
  {% if pdm %}
21
21
  dependencies = [
22
- "httpx>=0.20.0,<0.28.0",
23
- "attrs>=21.3.0",
22
+ "httpx>=0.20.0,<0.29.0",
23
+ "attrs>=22.2.0",
24
24
  "python-dateutil>=2.8.0",
25
25
  ]
26
26
 
@@ -31,8 +31,8 @@ distribution = true
31
31
 
32
32
  [tool.poetry.dependencies]
33
33
  python = "^3.9"
34
- httpx = ">=0.20.0,<0.28.0"
35
- attrs = ">=21.3.0"
34
+ httpx = ">=0.20.0,<0.29.0"
35
+ attrs = ">=22.2.0"
36
36
  python-dateutil = "^2.8.0"
37
37
  {% endif %}
38
38
 
@@ -13,6 +13,6 @@ setup(
13
13
  long_description_content_type="text/markdown",
14
14
  packages=find_packages(),
15
15
  python_requires=">=3.9, <4",
16
- install_requires=["httpx >= 0.20.0, < 0.28.0", "attrs >= 21.3.0", "python-dateutil >= 2.8.0, < 3"],
16
+ install_requires=["httpx >= 0.20.0, < 0.29.0", "attrs >= 22.2.0", "python-dateutil >= 2.8.0, < 3"],
17
17
  package_data={"{{ package_name }}": ["py.typed"]},
18
18
  )
@@ -6,19 +6,19 @@ license = { text = "MIT" }
6
6
  requires-python = ">=3.9,<4.0"
7
7
  dependencies = [
8
8
  "jinja2>=3.0.0,<4.0.0",
9
- "typer>0.6,<0.14",
9
+ "typer>0.6,<0.16",
10
10
  "colorama>=0.4.3; sys_platform == \"win32\"",
11
11
  "shellingham>=1.3.2,<2.0.0",
12
12
  "pydantic>=2.1.1,<3.0.0",
13
- "attrs>=21.3.0",
13
+ "attrs>=22.2.0",
14
14
  "python-dateutil>=2.8.1,<3.0.0",
15
- "httpx>=0.20.0,<0.28.0",
15
+ "httpx>=0.20.0,<0.29.0",
16
16
  "ruamel.yaml>=0.18.6,<0.19.0",
17
- "ruff>=0.2,<0.9",
17
+ "ruff>=0.2,<0.10",
18
18
  "typing-extensions>=4.8.0,<5.0.0",
19
19
  ]
20
20
  name = "openapi-python-client"
21
- version = "0.22.0"
21
+ version = "0.23.1"
22
22
  description = "Generate modern Python clients from OpenAPI"
23
23
  keywords = [
24
24
  "OpenAPI",
@@ -87,10 +87,9 @@ junit_family = "xunit2"
87
87
 
88
88
  [tool.pdm.dev-dependencies]
89
89
  dev = [
90
- "pytest",
91
- "pytest-mock",
92
- "mypy",
93
- "taskipy",
90
+ "pytest>8",
91
+ "pytest-mock>3",
92
+ "mypy>=1.13",
94
93
  "pytest-cov",
95
94
  "python-multipart",
96
95
  "types-PyYAML<7.0.0,>=6.0.3",
@@ -116,6 +115,7 @@ regen = {composite = ["regen_e2e", "regen_integration"]}
116
115
  e2e = "pytest openapi_python_client end_to_end_tests/test_end_to_end.py"
117
116
  re = {composite = ["regen_e2e", "e2e --snapshot-update"]}
118
117
  regen_e2e = "python -m end_to_end_tests.regen_golden_record"
118
+ unit_test = "pytest tests"
119
119
 
120
120
  [tool.pdm.scripts.test]
121
121
  cmd = "pytest tests end_to_end_tests/test_end_to_end.py --basetemp=tests/tmp"
@@ -130,7 +130,7 @@ composite = ["test --cov openapi_python_client tests --cov-report=term-missing"]
130
130
 
131
131
  [tool.pdm.scripts.regen_integration]
132
132
  shell = """
133
- openapi-python-client generate --overwrite --url https://raw.githubusercontent.com/openapi-generators/openapi-test-server/main/openapi.json --config integration-tests/config.yaml --meta none --output-path integration-tests/integration_tests \
133
+ openapi-python-client generate --overwrite --url https://raw.githubusercontent.com/openapi-generators/openapi-test-server/main/openapi.json --config integration-tests/config.yaml --meta pdm --output-path integration-tests \
134
134
  """
135
135
 
136
136
  [build-system]