openapi-python-client 0.29.1__tar.gz → 0.30.0__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 (115) hide show
  1. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/PKG-INFO +7 -5
  2. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/README.md +5 -3
  3. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/__init__.py +4 -4
  4. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/cli.py +9 -1
  5. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/config.py +1 -0
  6. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/parser/properties/__init__.py +2 -0
  7. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/parser/properties/any.py +1 -0
  8. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/parser/properties/boolean.py +1 -0
  9. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/parser/properties/date.py +1 -0
  10. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/parser/properties/datetime.py +1 -0
  11. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/parser/properties/file.py +1 -0
  12. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/parser/properties/float.py +1 -0
  13. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/parser/properties/int.py +1 -0
  14. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/parser/properties/model_property.py +1 -1
  15. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/parser/properties/none.py +1 -0
  16. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/parser/properties/string.py +1 -0
  17. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/parser/properties/uuid.py +1 -0
  18. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/parser/responses.py +1 -1
  19. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/schema.py +2 -2
  20. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/README.md.jinja +6 -6
  21. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/client.py.jinja +28 -28
  22. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/endpoint_macros.py.jinja +1 -1
  23. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/endpoint_module.py.jinja +6 -9
  24. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/pyproject_pdm.toml.jinja +1 -1
  25. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/pyproject_poetry.toml.jinja +1 -1
  26. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/pyproject_uv.toml.jinja +2 -2
  27. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/setup.py.jinja +1 -1
  28. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/types.py.jinja +2 -2
  29. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/pyproject.toml +11 -7
  30. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/.gitignore +0 -0
  31. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/LICENSE +0 -0
  32. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/__main__.py +0 -0
  33. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/parser/__init__.py +0 -0
  34. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/parser/bodies.py +0 -0
  35. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/parser/errors.py +0 -0
  36. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/parser/openapi.py +0 -0
  37. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/parser/properties/const.py +0 -0
  38. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/parser/properties/enum_property.py +0 -0
  39. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/parser/properties/list_property.py +0 -0
  40. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/parser/properties/literal_enum_property.py +0 -0
  41. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/parser/properties/merge_properties.py +0 -0
  42. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/parser/properties/property.py +0 -0
  43. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/parser/properties/protocol.py +0 -0
  44. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/parser/properties/schemas.py +0 -0
  45. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/parser/properties/union.py +0 -0
  46. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/py.typed +0 -0
  47. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/3.0.3.md +0 -0
  48. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/3.1.0.md +0 -0
  49. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/__init__.py +0 -0
  50. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/data_type.py +0 -0
  51. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/LICENSE +0 -0
  52. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/README.md +0 -0
  53. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/__init__.py +0 -0
  54. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/callback.py +0 -0
  55. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/components.py +0 -0
  56. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/contact.py +0 -0
  57. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/discriminator.py +0 -0
  58. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/encoding.py +0 -0
  59. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/example.py +0 -0
  60. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/external_documentation.py +0 -0
  61. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/header.py +0 -0
  62. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/info.py +0 -0
  63. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/license.py +0 -0
  64. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/link.py +0 -0
  65. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/media_type.py +0 -0
  66. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/oauth_flow.py +0 -0
  67. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/oauth_flows.py +0 -0
  68. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/open_api.py +0 -0
  69. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/operation.py +0 -0
  70. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/parameter.py +0 -0
  71. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/path_item.py +0 -0
  72. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/paths.py +0 -0
  73. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/reference.py +0 -0
  74. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/request_body.py +0 -0
  75. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/response.py +0 -0
  76. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/responses.py +0 -0
  77. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/security_requirement.py +0 -0
  78. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/security_scheme.py +0 -0
  79. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/server.py +0 -0
  80. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/server_variable.py +0 -0
  81. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/tag.py +0 -0
  82. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/openapi_schema_pydantic/xml.py +0 -0
  83. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/parameter_location.py +0 -0
  84. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/ref.py +0 -0
  85. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/schema/untrusted_string.py +0 -0
  86. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/strings.py +0 -0
  87. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/.gitignore.jinja +0 -0
  88. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/api_init.py.jinja +0 -0
  89. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/endpoint_init.py.jinja +0 -0
  90. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/errors.py.jinja +0 -0
  91. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/helpers.jinja +0 -0
  92. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/int_enum.py.jinja +0 -0
  93. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/literal_enum.py.jinja +0 -0
  94. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/model.py.jinja +0 -0
  95. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/models_init.py.jinja +0 -0
  96. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/package_init.py.jinja +0 -0
  97. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/property_templates/any_property.py.jinja +0 -0
  98. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/property_templates/boolean_property.py.jinja +0 -0
  99. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/property_templates/const_property.py.jinja +0 -0
  100. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/property_templates/date_property.py.jinja +0 -0
  101. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/property_templates/datetime_property.py.jinja +0 -0
  102. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/property_templates/enum_property.py.jinja +0 -0
  103. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/property_templates/file_property.py.jinja +0 -0
  104. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/property_templates/float_property.py.jinja +0 -0
  105. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/property_templates/helpers.jinja +0 -0
  106. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/property_templates/int_property.py.jinja +0 -0
  107. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/property_templates/list_property.py.jinja +0 -0
  108. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/property_templates/literal_enum_property.py.jinja +0 -0
  109. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/property_templates/model_property.py.jinja +0 -0
  110. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/property_templates/property_macros.py.jinja +0 -0
  111. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/property_templates/union_property.py.jinja +0 -0
  112. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/property_templates/uuid_property.py.jinja +0 -0
  113. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/pyproject.toml.jinja +0 -0
  114. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/pyproject_ruff.toml.jinja +0 -0
  115. {openapi_python_client-0.29.1 → openapi_python_client-0.30.0}/openapi_python_client/templates/str_enum.py.jinja +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: openapi-python-client
3
- Version: 0.29.1
3
+ Version: 0.30.0
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>
@@ -19,7 +19,7 @@ Classifier: Typing :: Typed
19
19
  Requires-Python: <4.0,>=3.11
20
20
  Requires-Dist: attrs>=22.2.0
21
21
  Requires-Dist: colorama>=0.4.3; sys_platform == 'win32'
22
- Requires-Dist: httpx<0.29.0,>=0.23.1
22
+ Requires-Dist: httpx2<3,>=2.13.1
23
23
  Requires-Dist: jinja2<4.0.0,>=3.0.0
24
24
  Requires-Dist: pydantic<3.0.0,>=2.10
25
25
  Requires-Dist: ruamel-yaml<0.20.0,>=0.18.6
@@ -91,7 +91,8 @@ _Be forewarned, this is a beta-level feature in the sense that the API exposed i
91
91
 
92
92
  ## What You Get
93
93
 
94
- 1. A `pyproject.toml` file, optionally with [Poetry] metadata (default), [PDM] (with `--meta=pdm`), or only [Ruff] config.
94
+ 1. A `pyproject.toml` file, optionally with [Poetry] metadata (default), [uv] (with `--meta=uv`), [PDM]
95
+ (with `--meta=pdm`), or only [Ruff] config.
95
96
  2. A `README.md` you'll most definitely need to update with your project's details
96
97
  3. A Python module named just like the auto-generated project name (e.g. "my_api_client") which contains:
97
98
  1. A `client` module which will have both a `Client` class and an `AuthenticatedClient` class. You'll need these
@@ -230,7 +231,7 @@ This extension has been adopted by similar projects such as [OpenAPI Tools](http
230
231
  It is intended to provide user-friendly names for integer Enum members that get generated.
231
232
  It is critical that the length of the array matches that of the enum values.
232
233
 
233
- ```
234
+ ```json
234
235
  "Colors": {
235
236
  "type": "integer",
236
237
  "format": "int32",
@@ -248,7 +249,7 @@ It is critical that the length of the array matches that of the enum values.
248
249
  ```
249
250
 
250
251
  Results in:
251
- ```
252
+ ```python
252
253
  class Color(IntEnum):
253
254
  RED = 0
254
255
  GREEN = 1
@@ -257,5 +258,6 @@ class Color(IntEnum):
257
258
 
258
259
  [changelog.md]: CHANGELOG.md
259
260
  [poetry]: https://python-poetry.org/
261
+ [uv]: https://docs.astral.sh/uv/
260
262
  [PDM]: https://pdm-project.org/latest/
261
263
  [Ruff]: https://docs.astral.sh/ruff/
@@ -61,7 +61,8 @@ _Be forewarned, this is a beta-level feature in the sense that the API exposed i
61
61
 
62
62
  ## What You Get
63
63
 
64
- 1. A `pyproject.toml` file, optionally with [Poetry] metadata (default), [PDM] (with `--meta=pdm`), or only [Ruff] config.
64
+ 1. A `pyproject.toml` file, optionally with [Poetry] metadata (default), [uv] (with `--meta=uv`), [PDM]
65
+ (with `--meta=pdm`), or only [Ruff] config.
65
66
  2. A `README.md` you'll most definitely need to update with your project's details
66
67
  3. A Python module named just like the auto-generated project name (e.g. "my_api_client") which contains:
67
68
  1. A `client` module which will have both a `Client` class and an `AuthenticatedClient` class. You'll need these
@@ -200,7 +201,7 @@ This extension has been adopted by similar projects such as [OpenAPI Tools](http
200
201
  It is intended to provide user-friendly names for integer Enum members that get generated.
201
202
  It is critical that the length of the array matches that of the enum values.
202
203
 
203
- ```
204
+ ```json
204
205
  "Colors": {
205
206
  "type": "integer",
206
207
  "format": "int32",
@@ -218,7 +219,7 @@ It is critical that the length of the array matches that of the enum values.
218
219
  ```
219
220
 
220
221
  Results in:
221
- ```
222
+ ```python
222
223
  class Color(IntEnum):
223
224
  RED = 0
224
225
  GREEN = 1
@@ -227,5 +228,6 @@ class Color(IntEnum):
227
228
 
228
229
  [changelog.md]: CHANGELOG.md
229
230
  [poetry]: https://python-poetry.org/
231
+ [uv]: https://docs.astral.sh/uv/
230
232
  [PDM]: https://pdm-project.org/latest/
231
233
  [Ruff]: https://docs.astral.sh/ruff/
@@ -10,8 +10,8 @@ from pathlib import Path
10
10
  from subprocess import CalledProcessError
11
11
  from typing import Any
12
12
 
13
- import httpcore
14
- import httpx
13
+ import httpcore2
14
+ import httpx2
15
15
  from jinja2 import BaseLoader, ChoiceLoader, Environment, FileSystemLoader, PackageLoader
16
16
  from ruamel.yaml import YAML
17
17
  from ruamel.yaml.error import YAMLError
@@ -355,14 +355,14 @@ def _get_document(*, source: str | Path, timeout: int) -> dict[str, Any] | Gener
355
355
  content_type: str | None
356
356
  if isinstance(source, str):
357
357
  try:
358
- response = httpx.get(source, timeout=timeout)
358
+ response = httpx2.get(source, timeout=timeout)
359
359
  yaml_bytes = response.content
360
360
  if "content-type" in response.headers:
361
361
  content_type = response.headers["content-type"].split(";")[0]
362
362
  else: # pragma: no cover
363
363
  content_type = mimetypes.guess_type(source, strict=True)[0]
364
364
 
365
- except (httpx.HTTPError, httpcore.NetworkError):
365
+ except (httpx2.HTTPError, httpcore2.NetworkError):
366
366
  return GeneratorError(header="Could not get OpenAPI document from provided URL")
367
367
  else:
368
368
  yaml_bytes = source.read_bytes()
@@ -53,7 +53,14 @@ def _process_config(
53
53
  except Exception as err:
54
54
  raise typer.BadParameter("Unable to parse config") from err
55
55
 
56
- return Config.from_sources(config_file, meta_type, source, file_encoding, overwrite, output_path=output_path)
56
+ return Config.from_sources(
57
+ config_file=config_file,
58
+ meta_type=meta_type,
59
+ document_source=source,
60
+ file_encoding=file_encoding,
61
+ overwrite=overwrite,
62
+ output_path=output_path,
63
+ )
57
64
 
58
65
 
59
66
  # noinspection PyUnusedLocal
@@ -123,6 +130,7 @@ def handle_errors(errors: Sequence[GeneratorError], fail_on_warning: bool = Fals
123
130
 
124
131
  @app.command()
125
132
  def generate(
133
+ *,
126
134
  url: str | None = typer.Option(None, help="A URL to read the OpenAPI document from"),
127
135
  path: Path | None = typer.Option(None, help="A path to the OpenAPI document"),
128
136
  custom_template_path: Path | None = typer.Option(
@@ -86,6 +86,7 @@ class Config:
86
86
 
87
87
  @staticmethod
88
88
  def from_sources(
89
+ *,
89
90
  config_file: ConfigFile,
90
91
  meta_type: MetaType,
91
92
  document_source: Path | str,
@@ -105,6 +105,7 @@ def _string_based_property(
105
105
 
106
106
 
107
107
  def _property_from_ref(
108
+ *,
108
109
  name: UntrustedString,
109
110
  required: bool,
110
111
  parent: oai.Schema | None,
@@ -141,6 +142,7 @@ def _property_from_ref(
141
142
 
142
143
 
143
144
  def property_from_data( # noqa: PLR0911, PLR0912
145
+ *,
144
146
  name: UntrustedString,
145
147
  required: bool,
146
148
  data: oai.Reference | oai.Schema,
@@ -16,6 +16,7 @@ class AnyProperty(PropertyProtocol):
16
16
  @classmethod
17
17
  def build(
18
18
  cls,
19
+ *,
19
20
  name: UntrustedString,
20
21
  required: bool,
21
22
  default: Any,
@@ -34,6 +34,7 @@ class BooleanProperty(PropertyProtocol):
34
34
  @classmethod
35
35
  def build(
36
36
  cls,
37
+ *,
37
38
  name: oai.UntrustedString,
38
39
  required: bool,
39
40
  default: Any,
@@ -29,6 +29,7 @@ class DateProperty(PropertyProtocol):
29
29
  @classmethod
30
30
  def build(
31
31
  cls,
32
+ *,
32
33
  name: oai.UntrustedString,
33
34
  required: bool,
34
35
  default: Any,
@@ -31,6 +31,7 @@ class DateTimeProperty(PropertyProtocol):
31
31
  @classmethod
32
32
  def build(
33
33
  cls,
34
+ *,
34
35
  name: oai.UntrustedString,
35
36
  required: bool,
36
37
  default: Any,
@@ -29,6 +29,7 @@ class FileProperty(PropertyProtocol):
29
29
  @classmethod
30
30
  def build(
31
31
  cls,
32
+ *,
32
33
  name: oai.UntrustedString,
33
34
  required: bool,
34
35
  default: Any,
@@ -34,6 +34,7 @@ class FloatProperty(PropertyProtocol):
34
34
  @classmethod
35
35
  def build(
36
36
  cls,
37
+ *,
37
38
  name: oai.UntrustedString,
38
39
  required: bool,
39
40
  default: Any,
@@ -34,6 +34,7 @@ class IntProperty(PropertyProtocol):
34
34
  @classmethod
35
35
  def build(
36
36
  cls,
37
+ *,
37
38
  name: oai.UntrustedString,
38
39
  required: bool,
39
40
  default: Any,
@@ -347,7 +347,7 @@ ANY_ADDITIONAL_PROPERTY = AnyProperty.build(
347
347
 
348
348
  def _get_additional_properties(
349
349
  *,
350
- schema_additional: None | (bool | (oai.Reference | oai.Schema)),
350
+ schema_additional: bool | oai.Reference | oai.Schema | None,
351
351
  schemas: Schemas,
352
352
  class_name: strings.ClassName,
353
353
  config: Config,
@@ -32,6 +32,7 @@ class NoneProperty(PropertyProtocol):
32
32
  @classmethod
33
33
  def build(
34
34
  cls,
35
+ *,
35
36
  name: oai.UntrustedString,
36
37
  required: bool,
37
38
  default: Any,
@@ -32,6 +32,7 @@ class StringProperty(PropertyProtocol):
32
32
  @classmethod
33
33
  def build(
34
34
  cls,
35
+ *,
35
36
  name: oai.UntrustedString,
36
37
  required: bool,
37
38
  default: Any,
@@ -35,6 +35,7 @@ class UuidProperty(PropertyProtocol):
35
35
  @classmethod
36
36
  def build(
37
37
  cls,
38
+ *,
38
39
  name: oai.UntrustedString,
39
40
  required: bool,
40
41
  default: Any,
@@ -31,7 +31,7 @@ class Responses:
31
31
 
32
32
 
33
33
  class _ResponseSource(TypedDict):
34
- """What data should be pulled from the httpx Response object"""
34
+ """What data should be pulled from the httpx2 Response object"""
35
35
 
36
36
  attribute: str
37
37
  return_type: str
@@ -36,8 +36,8 @@ class Schema(BaseModel):
36
36
  maxProperties: int | None = Field(default=None, ge=0)
37
37
  minProperties: int | None = Field(default=None, ge=0)
38
38
  required: list[UntrustedString] | None = Field(default=None)
39
- enum: None | list[Any] = Field(default=None, min_length=1)
40
- const: None | StrictStr | StrictInt | StrictFloat | StrictBool = None
39
+ enum: list[Any] | None = Field(default=None, min_length=1)
40
+ const: StrictStr | StrictInt | StrictFloat | StrictBool | None = None
41
41
  type: DataType | list[DataType] | None = Field(default=None)
42
42
  allOf: list[ReferenceOr["Schema"]] = Field(default_factory=list)
43
43
  oneOf: list[ReferenceOr["Schema"]] = Field(default_factory=list)
@@ -76,7 +76,7 @@ Things to know:
76
76
 
77
77
  ## Advanced customizations
78
78
 
79
- There are more settings on the generated `Client` class which let you control more runtime behavior, check out the docstring on that class for more info. You can also customize the underlying `httpx.Client` or `httpx.AsyncClient` (depending on your use-case):
79
+ There are more settings on the generated `Client` class which let you control more runtime behavior, check out the docstring on that class for more info. You can also customize the underlying `httpx2.Client` or `httpx2.AsyncClient` (depending on your use-case):
80
80
 
81
81
  ```python
82
82
  from {{ package_name }} import Client
@@ -93,20 +93,20 @@ client = Client(
93
93
  httpx_args={"event_hooks": {"request": [log_request], "response": [log_response]}},
94
94
  )
95
95
 
96
- # Or get the underlying httpx client to modify directly with client.get_httpx_client() or client.get_async_httpx_client()
96
+ # Or get the underlying httpx2 client to modify directly with client.get_httpx_client() or client.get_async_httpx_client()
97
97
  ```
98
98
 
99
- You can even set the httpx client directly, but beware that this will override any existing settings (e.g., base_url):
99
+ You can even set the httpx2 client directly, but beware that this will override any existing settings (e.g., base_url):
100
100
 
101
101
  ```python
102
- import httpx
102
+ import httpx2
103
103
  from {{ package_name }} import Client
104
104
 
105
105
  client = Client(
106
106
  base_url="https://api.example.com",
107
107
  )
108
108
  # Note that base_url needs to be re-set, as would any shared cookies, headers, etc.
109
- client.set_httpx_client(httpx.Client(base_url="https://api.example.com", proxies="http://localhost:8030"))
109
+ client.set_httpx_client(httpx2.Client(base_url="https://api.example.com", proxy="http://localhost:8030"))
110
110
  ```
111
111
 
112
112
  {% if meta == "poetry" %}
@@ -136,4 +136,4 @@ If you want to install this client into another project without publishing it (e
136
136
  1. If that project is not using uv:
137
137
  1. Build a wheel with `uv build --wheel`.
138
138
  1. Install that wheel from the other project `pip install <path-to-wheel>`.
139
- {% endif %}
139
+ {% endif %}
@@ -2,7 +2,7 @@ import ssl
2
2
  from typing import Any, Self
3
3
 
4
4
  from attrs import define, field, evolve
5
- import httpx
5
+ import httpx2
6
6
 
7
7
 
8
8
  {% set attrs_info = {
@@ -34,8 +34,8 @@ import httpx
34
34
  class Client:
35
35
  """A class for keeping track of data related to the API
36
36
 
37
- {% macro httpx_args_docstring() %}
38
- The following are accepted as keyword arguments and will be used to construct httpx Clients internally:
37
+ {% macro httpx2_args_docstring() %}
38
+ The following are accepted as keyword arguments and will be used to construct httpx2 Clients internally:
39
39
 
40
40
  ``base_url``: The base URL for the API, all requests are made to a relative path to this URL
41
41
 
@@ -44,16 +44,16 @@ class Client:
44
44
  ``headers``: A dictionary of headers to be sent with every request
45
45
 
46
46
  ``timeout``: The maximum amount of a time a request can take. API functions will raise
47
- httpx.TimeoutException if this is exceeded.
47
+ httpx2.TimeoutException if this is exceeded.
48
48
 
49
49
  ``verify_ssl``: Whether or not to verify the SSL certificate of the API server. This should be True in production,
50
50
  but can be set to False for testing purposes.
51
51
 
52
52
  ``follow_redirects``: Whether or not to follow redirects. Default value is False.
53
53
 
54
- ``httpx_args``: A dictionary of additional arguments to be passed to the ``httpx.Client`` and ``httpx.AsyncClient`` constructor.
54
+ ``httpx_args``: A dictionary of additional arguments to be passed to the ``httpx2.Client`` and ``httpx2.AsyncClient`` constructor.
55
55
  {% endmacro %}
56
- {{ httpx_args_docstring() }}
56
+ {{ httpx2_args_docstring() }}
57
57
  {% if not config.docstrings_on_attributes %}
58
58
 
59
59
  Attributes:
@@ -65,12 +65,12 @@ class Client:
65
65
  _base_url: str = field(alias="base_url")
66
66
  _cookies: dict[str, str] = field(factory=dict, kw_only=True, alias="cookies")
67
67
  _headers: dict[str, str] = field(factory=dict, kw_only=True, alias="headers")
68
- _timeout: httpx.Timeout | None = field(default=None, kw_only=True, alias="timeout")
68
+ _timeout: httpx2.Timeout | None = field(default=None, kw_only=True, alias="timeout")
69
69
  _verify_ssl: str | bool | ssl.SSLContext = field(default=True, kw_only=True, alias="verify_ssl")
70
70
  _follow_redirects: bool = field(default=False, kw_only=True, alias="follow_redirects")
71
71
  _httpx_args: dict[str, Any] = field(factory=dict, kw_only=True, alias="httpx_args")
72
- _client: httpx.Client | None = field(default=None, init=False)
73
- _async_client: httpx.AsyncClient | None = field(default=None, init=False)
72
+ _client: httpx2.Client | None = field(default=None, init=False)
73
+ _async_client: httpx2.AsyncClient | None = field(default=None, init=False)
74
74
  {% endmacro %}{{ attributes() }}
75
75
  {% macro builders(self) %}
76
76
  def with_headers(self, headers: dict[str, str]) -> "{{ self }}":
@@ -89,7 +89,7 @@ class Client:
89
89
  self._async_client.cookies.update(cookies)
90
90
  return evolve(self, cookies={**self._cookies, **cookies})
91
91
 
92
- def with_timeout(self, timeout: httpx.Timeout) -> "{{ self }}":
92
+ def with_timeout(self, timeout: httpx2.Timeout) -> "{{ self }}":
93
93
  """Get a new client matching this one with a new timeout configuration"""
94
94
  if self._client is not None:
95
95
  self._client.timeout = timeout
@@ -97,22 +97,22 @@ class Client:
97
97
  self._async_client.timeout = timeout
98
98
  return evolve(self, timeout=timeout)
99
99
  {% endmacro %}{{ builders("Client") }}
100
- {% macro httpx_stuff(name, custom_constructor=None) %}
101
- def set_httpx_client(self, client: httpx.Client) -> Self:
102
- """Manually set the underlying httpx.Client
100
+ {% macro httpx2_stuff(name, custom_constructor=None) %}
101
+ def set_httpx_client(self, client: httpx2.Client) -> Self:
102
+ """Manually set the underlying httpx2.Client
103
103
 
104
104
  **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout.
105
105
  """
106
106
  self._client = client
107
107
  return self
108
108
 
109
- def get_httpx_client(self) -> httpx.Client:
110
- """Get the underlying httpx.Client, constructing a new one if not previously set"""
109
+ def get_httpx_client(self) -> httpx2.Client:
110
+ """Get the underlying httpx2.Client, constructing a new one if not previously set"""
111
111
  if self._client is None:
112
112
  {% if custom_constructor %}
113
113
  {{ custom_constructor | indent(12) }}
114
114
  {% endif %}
115
- self._client = httpx.Client(
115
+ self._client = httpx2.Client(
116
116
  base_url=self._base_url,
117
117
  cookies=self._cookies,
118
118
  headers=self._headers,
@@ -124,29 +124,29 @@ class Client:
124
124
  return self._client
125
125
 
126
126
  def __enter__(self) -> Self:
127
- """Enter a context manager for self.client—you cannot enter twice (see httpx docs)"""
127
+ """Enter a context manager for self.client—you cannot enter twice (see httpx2 docs)"""
128
128
  self.get_httpx_client().__enter__()
129
129
  return self
130
130
 
131
131
  def __exit__(self, *args: Any, **kwargs: Any) -> None:
132
- """Exit a context manager for internal httpx.Client (see httpx docs)"""
132
+ """Exit a context manager for internal httpx2.Client (see httpx2 docs)"""
133
133
  self.get_httpx_client().__exit__(*args, **kwargs)
134
134
 
135
- def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> Self:
136
- """Manually set the underlying httpx.AsyncClient
135
+ def set_async_httpx_client(self, async_client: httpx2.AsyncClient) -> Self:
136
+ """Manually set the underlying httpx2.AsyncClient
137
137
 
138
138
  **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout.
139
139
  """
140
140
  self._async_client = async_client
141
141
  return self
142
142
 
143
- def get_async_httpx_client(self) -> httpx.AsyncClient:
144
- """Get the underlying httpx.AsyncClient, constructing a new one if not previously set"""
143
+ def get_async_httpx_client(self) -> httpx2.AsyncClient:
144
+ """Get the underlying httpx2.AsyncClient, constructing a new one if not previously set"""
145
145
  if self._async_client is None:
146
146
  {% if custom_constructor %}
147
147
  {{ custom_constructor | indent(12) }}
148
148
  {% endif %}
149
- self._async_client = httpx.AsyncClient(
149
+ self._async_client = httpx2.AsyncClient(
150
150
  base_url=self._base_url,
151
151
  cookies=self._cookies,
152
152
  headers=self._headers,
@@ -158,20 +158,20 @@ class Client:
158
158
  return self._async_client
159
159
 
160
160
  async def __aenter__(self) -> Self:
161
- """Enter a context manager for underlying httpx.AsyncClient—you cannot enter twice (see httpx docs)"""
161
+ """Enter a context manager for underlying httpx2.AsyncClient—you cannot enter twice (see httpx2 docs)"""
162
162
  await self.get_async_httpx_client().__aenter__()
163
163
  return self
164
164
 
165
165
  async def __aexit__(self, *args: Any, **kwargs: Any) -> None:
166
- """Exit a context manager for underlying httpx.AsyncClient (see httpx docs)"""
166
+ """Exit a context manager for underlying httpx2.AsyncClient (see httpx2 docs)"""
167
167
  await self.get_async_httpx_client().__aexit__(*args, **kwargs)
168
- {% endmacro %}{{ httpx_stuff("Client") }}
168
+ {% endmacro %}{{ httpx2_stuff("Client") }}
169
169
 
170
170
  @define
171
171
  class AuthenticatedClient:
172
172
  """A Client which has been authenticated for use on secured endpoints
173
173
 
174
- {{ httpx_args_docstring() }}
174
+ {{ httpx2_args_docstring() }}
175
175
  {% if not config.docstrings_on_attributes %}
176
176
 
177
177
  Attributes:
@@ -188,4 +188,4 @@ class AuthenticatedClient:
188
188
  {{ declare_attr("auth_header_name") | indent(4) }}
189
189
 
190
190
  {{ builders("AuthenticatedClient") }}
191
- {{ httpx_stuff("AuthenticatedClient", "self._headers[self.auth_header_name] = f\"{self.prefix} {self.token}\" if self.prefix else self.token") }}
191
+ {{ httpx2_stuff("AuthenticatedClient", "self._headers[self.auth_header_name] = f\"{self.prefix} {self.token}\" if self.prefix else self.token") }}
@@ -184,7 +184,7 @@ Args:
184
184
  {% endif %}
185
185
  Raises:
186
186
  errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
187
- httpx.TimeoutException: If the request takes longer than Client.timeout.
187
+ httpx2.TimeoutException: If the request takes longer than Client.timeout.
188
188
 
189
189
  Returns:
190
190
  {% if is_detailed %}
@@ -2,7 +2,7 @@ from http import HTTPStatus
2
2
  from typing import Any, cast
3
3
  from urllib.parse import quote
4
4
 
5
- import httpx
5
+ import httpx2
6
6
 
7
7
  from ...client import AuthenticatedClient, Client
8
8
  from ...types import Response, UNSET
@@ -50,18 +50,15 @@ def _get_kwargs(
50
50
  {% for body in endpoint.bodies %}
51
51
  if isinstance(body, {{body.prop.get_type_string(no_optional=True) | as_unembedded_code }}):
52
52
  {{ body_to_kwarg(body) | indent(8) }}
53
- {%- if body.content_type == "multipart/form-data" %}
54
- headers["Content-Type"] = "multipart/form-data; boundary=+++"
55
- {% else %}
53
+ {#- httpx2 sets multipart/form-data with a random boundary itself, a fixed one could appear in the content #}
54
+ {%- if body.content_type != "multipart/form-data" %}
56
55
  headers["Content-Type"] = "{{ body.content_type | in_double_quote_literal }}"
57
56
  {% endif %}
58
57
  {% endfor %}
59
58
  {% elif endpoint.bodies | length == 1 %}
60
59
  {% set body = endpoint.bodies[0] %}
61
60
  {{ body_to_kwarg(body) | indent(4) }}
62
- {%- if body.content_type == "multipart/form-data" %}
63
- headers["Content-Type"] = "multipart/form-data; boundary=+++"
64
- {% else %}
61
+ {%- if body.content_type != "multipart/form-data" %}
65
62
  headers["Content-Type"] = "{{ body.content_type | in_double_quote_literal }}"
66
63
  {% endif %}
67
64
  {% endif %}
@@ -78,7 +75,7 @@ def _get_kwargs(
78
75
  {% endif %}
79
76
 
80
77
 
81
- def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> {{return_type}}:
78
+ def _parse_response(*, client: AuthenticatedClient | Client, response: httpx2.Response) -> {{return_type}}:
82
79
  {% for response in endpoint.responses.patterns %}
83
80
  {% set code_range = response.status_code.range %}
84
81
  {% if code_range[0] == code_range[1] %}
@@ -98,7 +95,7 @@ def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Res
98
95
  {% endif %}
99
96
 
100
97
 
101
- def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[{{ return_string | as_unembedded_code }}]:
98
+ def _build_response(*, client: AuthenticatedClient | Client, response: httpx2.Response) -> Response[{{ return_string | as_unembedded_code }}]:
102
99
  return Response(
103
100
  status_code=HTTPStatus(response.status_code),
104
101
  content=response.content,
@@ -6,7 +6,7 @@ authors = []
6
6
  readme = "README.md"
7
7
  requires-python = ">=3.11"
8
8
  dependencies = [
9
- "httpx>=0.23.1,<0.29.0",
9
+ "httpx2>=2.13.1,<3",
10
10
  "attrs>=22.2.0",
11
11
  ]
12
12
 
@@ -11,7 +11,7 @@ include = ["{{ package_name }}/py.typed"]
11
11
 
12
12
  [tool.poetry.dependencies]
13
13
  python = "^3.11"
14
- httpx = ">=0.23.1,<0.29.0"
14
+ httpx2 = ">=2.13.1,<3"
15
15
  attrs = ">=22.2.0"
16
16
 
17
17
  [build-system]
@@ -6,7 +6,7 @@ authors = []
6
6
  requires-python = ">=3.11"
7
7
  readme = "README.md"
8
8
  dependencies = [
9
- "httpx>=0.23.1,<0.29.0",
9
+ "httpx2>=2.13.1,<3",
10
10
  "attrs>=22.2.0",
11
11
  ]
12
12
 
@@ -15,5 +15,5 @@ module-name = "{{ package_name }}"
15
15
  module-root = ""
16
16
 
17
17
  [build-system]
18
- requires = ["uv_build>=0.12.0,<0.13.0"]
18
+ requires = ["uv_build>=0.13.0,<0.14.0"]
19
19
  build-backend = "uv_build"
@@ -13,6 +13,6 @@ setup(
13
13
  long_description_content_type="text/markdown",
14
14
  packages=find_packages(),
15
15
  python_requires=">=3.11, <4",
16
- install_requires=["httpx >= 0.23.1, < 0.29.0", "attrs >= 22.2.0"],
16
+ install_requires=["httpx2 >= 2.13.1, < 3", "attrs >= 22.2.0"],
17
17
  package_data={"{{ package_name }}": ["py.typed"]},
18
18
  )
@@ -14,7 +14,7 @@ class Unset:
14
14
 
15
15
  UNSET: Unset = Unset()
16
16
 
17
- # The types that `httpx.Client(files=)` can accept, copied from that library.
17
+ # The types that `httpx2.Client(files=)` can accept, copied from that library.
18
18
  FileContent = IO[bytes] | bytes | str
19
19
  FileTypes = (
20
20
  # (filename, file (or bytes), content_type)
@@ -33,7 +33,7 @@ class File:
33
33
  mime_type: str | None = None
34
34
 
35
35
  def to_tuple(self) -> FileTypes:
36
- """ Return a tuple representation that httpx will accept for multipart/form-data """
36
+ """ Return a tuple representation that httpx2 will accept for multipart/form-data """
37
37
  return self.file_name, self.payload, self.mime_type
38
38
 
39
39
 
@@ -11,12 +11,12 @@ dependencies = [
11
11
  "shellingham>=1.3.2,<2.0.0",
12
12
  "pydantic>=2.10,<3.0.0",
13
13
  "attrs>=22.2.0",
14
- "httpx>=0.23.1,<0.29.0",
14
+ "httpx2>=2.13.1,<3",
15
15
  "ruamel.yaml>=0.18.6,<0.20.0",
16
16
  "ruff>=0.2",
17
17
  ]
18
18
  name = "openapi-python-client"
19
- version = "0.29.1"
19
+ version = "0.30.0"
20
20
  description = "Generate modern Python clients from OpenAPI"
21
21
  keywords = [
22
22
  "OpenAPI",
@@ -44,15 +44,16 @@ openapi-python-client = "openapi_python_client.cli:app"
44
44
 
45
45
  [dependency-groups]
46
46
  dev = [
47
- "pytest>8",
48
- "pytest-mock>3",
49
47
  "mypy>=1.13",
48
+ "pytest>8",
50
49
  "pytest-cov",
50
+ "pytest-mock>3",
51
51
  "python-multipart",
52
- "types-PyYAML<7.0.0,>=6.0.3",
53
- "types-certifi<2021.10.9,>=2020.0.0",
52
+ "ruff>=0.2,<0.18",
54
53
  "syrupy>=4",
55
54
  "hypothesis>=6.100",
55
+ "types-PyYAML<7.0.0,>=6.0.3",
56
+ "types-certifi<2021.10.9,>=2020.0.0",
56
57
  ]
57
58
 
58
59
  [tool.ruff]
@@ -73,7 +74,7 @@ ignore = ["E501", "PLR0913", "PLR2004"]
73
74
 
74
75
  [tool.ruff.lint.per-file-ignores]
75
76
  "openapi_python_client/cli.py" = ["B008"]
76
- "tests/*" = ["PLR2004"]
77
+ "tests/*" = ["PLR2004", "PLR0917"]
77
78
 
78
79
  [tool.coverage.run]
79
80
  omit = ["openapi_python_client/__main__.py", "openapi_python_client/templates/*", "end_to_end_tests/*", "integration_tests/*", "tests/*"]
@@ -95,6 +96,9 @@ ignore_missing_imports = true
95
96
  [tool.pytest.ini_options]
96
97
  junit_family = "xunit2"
97
98
 
99
+ [tool.pdm.resolution]
100
+ exclude-newer = "7d"
101
+
98
102
  [tool.pdm.build]
99
103
  includes = [
100
104
  "openapi_python_client",