openapi-python-client 0.27.1__tar.gz → 0.28.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.27.1 → openapi_python_client-0.28.1}/PKG-INFO +3 -3
  2. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/parser/bodies.py +1 -1
  3. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/parser/properties/model_property.py +5 -0
  4. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/parser/properties/union.py +14 -9
  5. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/endpoint_macros.py.jinja +19 -6
  6. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/endpoint_module.py.jinja +3 -2
  7. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/model.py.jinja +5 -2
  8. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/property_templates/date_property.py.jinja +6 -4
  9. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/property_templates/datetime_property.py.jinja +7 -5
  10. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/property_templates/enum_property.py.jinja +2 -2
  11. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/property_templates/file_property.py.jinja +2 -2
  12. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/property_templates/list_property.py.jinja +2 -2
  13. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/property_templates/literal_enum_property.py.jinja +2 -2
  14. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/property_templates/model_property.py.jinja +3 -2
  15. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/property_templates/union_property.py.jinja +2 -2
  16. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/property_templates/uuid_property.py.jinja +7 -5
  17. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/pyproject.toml +3 -3
  18. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/.gitignore +0 -0
  19. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/LICENSE +0 -0
  20. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/README.md +0 -0
  21. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/__init__.py +0 -0
  22. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/__main__.py +0 -0
  23. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/cli.py +0 -0
  24. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/config.py +0 -0
  25. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/parser/__init__.py +0 -0
  26. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/parser/errors.py +0 -0
  27. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/parser/openapi.py +0 -0
  28. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/parser/properties/__init__.py +0 -0
  29. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/parser/properties/any.py +0 -0
  30. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/parser/properties/boolean.py +0 -0
  31. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/parser/properties/const.py +0 -0
  32. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/parser/properties/date.py +0 -0
  33. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/parser/properties/datetime.py +0 -0
  34. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/parser/properties/enum_property.py +0 -0
  35. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/parser/properties/file.py +0 -0
  36. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/parser/properties/float.py +0 -0
  37. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/parser/properties/int.py +0 -0
  38. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/parser/properties/list_property.py +0 -0
  39. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/parser/properties/literal_enum_property.py +0 -0
  40. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/parser/properties/merge_properties.py +0 -0
  41. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/parser/properties/none.py +0 -0
  42. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/parser/properties/property.py +0 -0
  43. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/parser/properties/protocol.py +0 -0
  44. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/parser/properties/schemas.py +0 -0
  45. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/parser/properties/string.py +0 -0
  46. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/parser/properties/uuid.py +0 -0
  47. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/parser/responses.py +0 -0
  48. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/py.typed +0 -0
  49. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/3.0.3.md +0 -0
  50. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/3.1.0.md +0 -0
  51. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/__init__.py +0 -0
  52. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/data_type.py +0 -0
  53. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/LICENSE +0 -0
  54. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/README.md +0 -0
  55. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/__init__.py +0 -0
  56. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/callback.py +0 -0
  57. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/components.py +0 -0
  58. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/contact.py +0 -0
  59. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/discriminator.py +0 -0
  60. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/encoding.py +0 -0
  61. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/example.py +0 -0
  62. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/external_documentation.py +0 -0
  63. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/header.py +0 -0
  64. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/info.py +0 -0
  65. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/license.py +0 -0
  66. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/link.py +0 -0
  67. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/media_type.py +0 -0
  68. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/oauth_flow.py +0 -0
  69. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/oauth_flows.py +0 -0
  70. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/open_api.py +0 -0
  71. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/operation.py +0 -0
  72. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/parameter.py +0 -0
  73. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/path_item.py +0 -0
  74. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/paths.py +0 -0
  75. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/reference.py +0 -0
  76. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/request_body.py +0 -0
  77. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/response.py +0 -0
  78. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/responses.py +0 -0
  79. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/schema.py +0 -0
  80. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/security_requirement.py +0 -0
  81. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/security_scheme.py +0 -0
  82. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/server.py +0 -0
  83. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/server_variable.py +0 -0
  84. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/tag.py +0 -0
  85. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/openapi_schema_pydantic/xml.py +0 -0
  86. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/schema/parameter_location.py +0 -0
  87. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/.gitignore.jinja +0 -0
  88. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/README.md.jinja +0 -0
  89. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/api_init.py.jinja +0 -0
  90. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/client.py.jinja +0 -0
  91. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/endpoint_init.py.jinja +0 -0
  92. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/errors.py.jinja +0 -0
  93. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/helpers.jinja +0 -0
  94. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/int_enum.py.jinja +0 -0
  95. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/literal_enum.py.jinja +0 -0
  96. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/models_init.py.jinja +0 -0
  97. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/package_init.py.jinja +0 -0
  98. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/property_templates/any_property.py.jinja +0 -0
  99. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/property_templates/boolean_property.py.jinja +0 -0
  100. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/property_templates/const_property.py.jinja +0 -0
  101. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/property_templates/float_property.py.jinja +0 -0
  102. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/property_templates/helpers.jinja +0 -0
  103. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/property_templates/int_property.py.jinja +0 -0
  104. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/property_templates/property_macros.py.jinja +0 -0
  105. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/pyproject.toml.jinja +0 -0
  106. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/pyproject_pdm.toml.jinja +0 -0
  107. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/pyproject_poetry.toml.jinja +0 -0
  108. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/pyproject_ruff.toml.jinja +0 -0
  109. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/pyproject_uv.toml.jinja +0 -0
  110. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/setup.py.jinja +0 -0
  111. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/str_enum.py.jinja +0 -0
  112. {openapi_python_client-0.27.1 → openapi_python_client-0.28.1}/openapi_python_client/templates/types.py.jinja +0 -0
  113. {openapi_python_client-0.27.1 → openapi_python_client-0.28.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.27.1
3
+ Version: 0.28.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>
@@ -25,10 +25,10 @@ Requires-Dist: httpx<0.29.0,>=0.23.0
25
25
  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
- Requires-Dist: ruamel-yaml<0.19.0,>=0.18.6
28
+ Requires-Dist: ruamel-yaml<0.20.0,>=0.18.6
29
29
  Requires-Dist: ruff>=0.2
30
30
  Requires-Dist: shellingham<2.0.0,>=1.3.2
31
- Requires-Dist: typer<0.21,>0.16
31
+ Requires-Dist: typer<0.22,>0.16
32
32
  Description-Content-Type: text/markdown
33
33
 
34
34
  ![Run Checks](https://github.com/openapi-generators/openapi-python-client/workflows/Run%20Checks/badge.svg)
@@ -99,7 +99,7 @@ def body_from_data(
99
99
  continue
100
100
  prop, schemas = property_from_data(
101
101
  name="body",
102
- required=True,
102
+ required=body.required,
103
103
  data=media_type_schema,
104
104
  schemas=schemas,
105
105
  parent_name=f"{endpoint_name}_{body_type}" if prefix_type_names else endpoint_name,
@@ -292,6 +292,11 @@ def _process_properties( # noqa: PLR0912, PLR0911
292
292
  unprocessed_props.extend(sub_prop.properties.items() if sub_prop.properties else [])
293
293
  required_set.update(sub_prop.required or [])
294
294
 
295
+ # Update properties that are marked as required in the schema
296
+ for prop_name in required_set:
297
+ if prop_name in properties and not properties[prop_name].required:
298
+ properties[prop_name] = evolve(properties[prop_name], required=True)
299
+
295
300
  for key, value in unprocessed_props:
296
301
  prop_required = key in required_set
297
302
  prop_or_error: Property | (PropertyError | None)
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from collections.abc import Iterator
3
4
  from itertools import chain
4
5
  from typing import Any, ClassVar, cast
5
6
 
@@ -88,22 +89,26 @@ class UnionProperty(PropertyProtocol):
88
89
  )
89
90
  sub_properties.append(sub_prop)
90
91
 
91
- def flatten_union_properties(sub_properties: list[PropertyProtocol]) -> list[PropertyProtocol]:
92
- flattened = []
93
- for sub_prop in sub_properties:
94
- if isinstance(sub_prop, UnionProperty):
95
- flattened.extend(flatten_union_properties(sub_prop.inner_properties))
92
+ def flatten_union_properties(possibly_nested: list[PropertyProtocol]) -> Iterator[PropertyProtocol]:
93
+ for to_flatten in possibly_nested:
94
+ if isinstance(to_flatten, UnionProperty):
95
+ yield from flatten_union_properties(to_flatten.inner_properties)
96
96
  else:
97
- flattened.append(sub_prop)
98
- return flattened
97
+ yield to_flatten
99
98
 
100
- sub_properties = flatten_union_properties(sub_properties)
99
+ seen_types = set()
100
+ inner_properties: list[PropertyProtocol] = []
101
+ for flattened in flatten_union_properties(sub_properties):
102
+ type_string = flattened.get_type_string(no_optional=True)
103
+ if type_string not in seen_types:
104
+ seen_types.add(type_string)
105
+ inner_properties.append(flattened)
101
106
 
102
107
  prop = UnionProperty(
103
108
  name=name,
104
109
  required=required,
105
110
  default=None,
106
- inner_properties=sub_properties,
111
+ inner_properties=inner_properties,
107
112
  python_name=PythonIdentifier(value=name, prefix=config.field_prefix),
108
113
  description=data.description,
109
114
  example=data.example,
@@ -60,13 +60,23 @@ params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
60
60
 
61
61
  {% macro body_to_kwarg(body) %}
62
62
  {% if body.body_type == "data" %}
63
+ {% if body.prop.required %}
63
64
  _kwargs["data"] = body.to_dict()
65
+ {% else %}
66
+ if not isinstance(body, Unset):
67
+ _kwargs["data"] = body.to_dict()
68
+ {% endif %}
64
69
  {% elif body.body_type == "files"%}
65
70
  {{ multipart_body(body) }}
66
71
  {% elif body.body_type == "json" %}
67
72
  {{ json_body(body) }}
68
73
  {% elif body.body_type == "content" %}
74
+ {% if body.prop.required %}
69
75
  _kwargs["content"] = body.payload
76
+ {% else %}
77
+ if not isinstance(body, Unset):
78
+ _kwargs["content"] = body.payload
79
+ {% endif %}
70
80
  {% endif %}
71
81
  {% endmacro %}
72
82
 
@@ -74,9 +84,12 @@ _kwargs["content"] = body.payload
74
84
  {% set property = body.prop %}
75
85
  {% import "property_templates/" + property.template as prop_template %}
76
86
  {% if prop_template.transform %}
77
- {{ prop_template.transform(property, property.python_name, "_kwargs[\"json\"]") }}
78
- {% else %}
87
+ {{ prop_template.transform(property, property.python_name, "_kwargs[\"json\"]", skip_unset=True, declare_type=False) }}
88
+ {% elif property.required %}
79
89
  _kwargs["json"] = {{ property.python_name }}
90
+ {% else %}
91
+ if not isinstance({{property.python_name}}, Unset):
92
+ _kwargs["json"] = {{ property.python_name }}
80
93
  {% endif %}
81
94
  {% endmacro %}
82
95
 
@@ -107,12 +120,12 @@ client: AuthenticatedClient | Client,
107
120
  {% endif %}
108
121
  {# Any allowed bodies #}
109
122
  {% if endpoint.bodies | length == 1 %}
110
- body: {{ endpoint.bodies[0].prop.get_type_string() }},
123
+ body: {{ endpoint.bodies[0].prop.get_type_string() }}{% if not endpoint.bodies[0].prop.required %} = UNSET{% endif %},
111
124
  {% elif endpoint.bodies | length > 1 %}
112
125
  body:
113
- {%- for body in endpoint.bodies -%}
114
- {{ body.prop.get_type_string() }} {% if not loop.last %} | {% endif %}
115
- {%- endfor -%}
126
+ {%- for body in endpoint.bodies -%}{% set body_required = body_required and body.prop.required %}
127
+ {{ body.prop.get_type_string(no_optional=True) }} {% if not loop.last %} | {% endif %}
128
+ {%- endfor -%}{% if not body_required %} | Unset = UNSET{% endif %}
116
129
  ,
117
130
  {% endif %}
118
131
  {# query parameters #}
@@ -1,5 +1,6 @@
1
1
  from http import HTTPStatus
2
2
  from typing import Any, cast
3
+ from urllib.parse import quote
3
4
 
4
5
  import httpx
5
6
 
@@ -31,7 +32,7 @@ def _get_kwargs(
31
32
  {% if endpoint.path_parameters %}
32
33
  "url": "{{ endpoint.path }}".format(
33
34
  {%- for parameter in endpoint.path_parameters -%}
34
- {{parameter.python_name}}={{parameter.python_name}},
35
+ {{parameter.python_name}}=quote(str({{parameter.python_name}}), safe=""),
35
36
  {%- endfor -%}
36
37
  ),
37
38
  {% else %}
@@ -47,7 +48,7 @@ def _get_kwargs(
47
48
 
48
49
  {% if endpoint.bodies | length > 1 %}
49
50
  {% for body in endpoint.bodies %}
50
- if isinstance(body, {{body.prop.get_type_string() }}):
51
+ if isinstance(body, {{body.prop.get_type_string(no_optional=True) }}):
51
52
  {{ body_to_kwarg(body) | indent(8) }}
52
53
  headers["Content-Type"] = "{{ body.content_type }}"
53
54
  {% endfor %}
@@ -16,7 +16,7 @@ from ..types import UNSET, Unset
16
16
  {{ relative }}
17
17
  {% endfor %}
18
18
 
19
- {% for lazy_import in model.lazy_imports %}
19
+ {% for lazy_import in model.lazy_imports | sort %}
20
20
  {% if loop.first %}
21
21
  if TYPE_CHECKING:
22
22
  {% endif %}
@@ -151,6 +151,9 @@ return field_dict
151
151
 
152
152
  {% if model.is_multipart_body %}
153
153
  def to_multipart(self) -> types.RequestFiles:
154
+ {% for lazy_import in model.lazy_imports %}
155
+ {{ lazy_import }}
156
+ {% endfor %}
154
157
  files: types.RequestFiles = []
155
158
 
156
159
  {% for property in model.required_properties + model.optional_properties %}
@@ -170,7 +173,7 @@ return field_dict
170
173
 
171
174
  @classmethod
172
175
  def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
173
- {% for lazy_import in model.lazy_imports %}
176
+ {% for lazy_import in model.lazy_imports | sort %}
174
177
  {{ lazy_import }}
175
178
  {% endfor %}
176
179
  {% if (model.required_properties or model.optional_properties or model.additional_properties) %}
@@ -10,16 +10,18 @@ isoparse({{ source }}).date()
10
10
 
11
11
  {% macro check_type_for_construct(property, source) %}isinstance({{ source }}, str){% endmacro %}
12
12
 
13
- {% macro transform(property, source, destination, declare_type=True) %}
13
+ {% macro transform(property, source, destination, declare_type=True, skip_unset=False) %}
14
14
  {% set transformed = source + ".isoformat()" %}
15
15
  {% if property.required %}
16
16
  {{ destination }} = {{ transformed }}
17
17
  {%- else %}
18
- {% if declare_type %}
19
- {% set type_annotation = property.get_type_string(json=True) %}
18
+ {% if not skip_unset %}
19
+ {% if declare_type %}
20
+ {% set type_annotation = property.get_type_string(json=True) %}
20
21
  {{ destination }}: {{ type_annotation }} = UNSET
21
- {% else %}
22
+ {% else %}
22
23
  {{ destination }} = UNSET
24
+ {% endif %}
23
25
  {% endif %}
24
26
  if not isinstance({{ source }}, Unset):
25
27
  {{ destination }} = {{ transformed }}
@@ -10,17 +10,19 @@ isoparse({{ source }})
10
10
 
11
11
  {% macro check_type_for_construct(property, source) %}isinstance({{ source }}, str){% endmacro %}
12
12
 
13
- {% macro transform(property, source, destination, declare_type=True) %}
13
+ {% macro transform(property, source, destination, declare_type=True, skip_unset=False) %}
14
14
  {% set transformed = source + ".isoformat()" %}
15
15
  {% if property.required %}
16
16
  {{ destination }} = {{ transformed }}
17
17
  {%- else %}
18
- {% if declare_type %}
19
- {% set type_annotation = property.get_type_string(json=True) %}
18
+ {% if not skip_unset %}
19
+ {% if declare_type %}
20
+ {% set type_annotation = property.get_type_string(json=True) %}
20
21
  {{ destination }}: {{ type_annotation }} = UNSET
21
- {% else %}
22
+ {% else %}
22
23
  {{ destination }} = UNSET
23
- {% endif %}
24
+ {% endif %}
25
+ {% endif %}
24
26
  if not isinstance({{ source }}, Unset):
25
27
  {{ destination }} = {{ transformed }}
26
28
  {%- endif %}
@@ -10,13 +10,13 @@
10
10
 
11
11
  {% macro check_type_for_construct(property, source) %}isinstance({{ source }}, {{ property.value_type.__name__ }}){% endmacro %}
12
12
 
13
- {% macro transform(property, source, destination, declare_type=True) %}
13
+ {% macro transform(property, source, destination, declare_type=True, skip_unset=False) %}
14
14
  {% set transformed = source + ".value" %}
15
15
  {% set type_string = property.get_type_string(json=True) %}
16
16
  {% if property.required %}
17
17
  {{ destination }} = {{ transformed }}
18
18
  {%- else %}
19
- {{ destination }}{% if declare_type %}: {{ type_string }}{% endif %} = UNSET
19
+ {% if not skip_unset %}{{ destination }}{% if declare_type %}: {{ type_string }}{% endif %} = UNSET{% endif +%}
20
20
  if not isinstance({{ source }}, Unset):
21
21
  {{ destination }} = {{ transformed }}
22
22
  {% endif %}
@@ -12,11 +12,11 @@ File(
12
12
 
13
13
  {% macro check_type_for_construct(property, source) %}isinstance({{ source }}, bytes){% endmacro %}
14
14
 
15
- {% macro transform(property, source, destination, declare_type=True) %}
15
+ {% macro transform(property, source, destination, declare_type=True, skip_unset=False) %}
16
16
  {% if property.required %}
17
17
  {{ destination }} = {{ source }}.to_tuple()
18
18
  {% else %}
19
- {{ destination }}{% if declare_type %}: {{ property.get_type_string(json=True) }}{% endif %} = UNSET
19
+ {% if not skip_unset %}{{ destination }}{% if declare_type %}: {{ property.get_type_string(json=True) }}{% endif %} = UNSET{% endif +%}
20
20
  if not isinstance({{ source }}, Unset):
21
21
  {{ destination }} = {{ source }}.to_tuple()
22
22
  {% endif %}
@@ -39,13 +39,13 @@ for {{ inner_source }} in {{ source }}:
39
39
 
40
40
  {% macro check_type_for_construct(property, source) %}isinstance({{ source }}, list){% endmacro %}
41
41
 
42
- {% macro transform(property, source, destination, declare_type=True) %}
42
+ {% macro transform(property, source, destination, declare_type=True, skip_unset=False) %}
43
43
  {% set inner_property = property.inner_property %}
44
44
  {% set type_string = property.get_type_string(json=True) %}
45
45
  {% if property.required %}
46
46
  {{ _transform(property, source, destination, "to_dict") }}
47
47
  {% else %}
48
- {{ destination }}{% if declare_type %}: {{ type_string }}{% endif %} = UNSET
48
+ {% if not skip_unset %}{{ destination }}{% if declare_type %}: {{ type_string }}{% endif %} = UNSET{% endif +%}
49
49
  if not isinstance({{ source }}, Unset):
50
50
  {{ _transform(property, source, destination, "to_dict") | indent(4)}}
51
51
  {% endif %}
@@ -10,12 +10,12 @@ check_{{ property.get_class_name_snake_case() }}({{ source }})
10
10
 
11
11
  {% macro check_type_for_construct(property, source) %}isinstance({{ source }}, {{ property.get_instance_type_string() }}){% endmacro %}
12
12
 
13
- {% macro transform(property, source, destination, declare_type=True) %}
13
+ {% macro transform(property, source, destination, declare_type=True, skip_unset=False) %}
14
14
  {% set type_string = property.get_type_string(json=True) %}
15
15
  {% if property.required %}
16
16
  {{ destination }}{% if declare_type %}: {{ type_string }}{% endif %} = {{ source }}
17
17
  {%- else %}
18
- {{ destination }}{% if declare_type %}: {{ type_string }}{% endif %} = UNSET
18
+ {% if not skip_unset %}{{ destination }}{% if declare_type %}: {{ type_string }}{% endif %} = UNSET{% endif +%}
19
19
  if not isinstance({{ source }}, Unset):
20
20
  {{ destination }} = {{ source }}
21
21
  {% endif %}
@@ -10,13 +10,14 @@
10
10
 
11
11
  {% macro check_type_for_construct(property, source) %}isinstance({{ source }}, dict){% endmacro %}
12
12
 
13
- {% macro transform(property, source, destination, declare_type=True) %}
13
+ {% macro transform(property, source, destination, declare_type=True, skip_unset=False) %}
14
14
  {% set transformed = source + ".to_dict()" %}
15
15
  {% set type_string = property.get_type_string(json=True) %}
16
16
  {% if property.required %}
17
17
  {{ destination }} = {{ transformed }}
18
18
  {%- else %}
19
- {{ destination }}{% if declare_type %}: {{ type_string }}{% endif %} = UNSET
19
+ {% if not skip_unset %}{{ destination }}{% if declare_type %}: {{ type_string }}{% endif %} = UNSET{% endif %}
20
+
20
21
  if not isinstance({{ source }}, Unset):
21
22
  {{ destination }} = {{ transformed }}
22
23
  {%- endif %}
@@ -39,11 +39,11 @@ def _parse_{{ property.python_name }}(data: object) -> {{ property.get_type_stri
39
39
  {{ property.python_name }} = _parse_{{ property.python_name }}({{ source }})
40
40
  {% endmacro %}
41
41
 
42
- {% macro transform(property, source, destination, declare_type=True) %}
42
+ {% macro transform(property, source, destination, declare_type=True, skip_unset=False) %}
43
43
  {% set ns = namespace(contains_properties_without_transform = false, contains_modified_properties = not property.required, has_if = false) %}
44
44
  {% if declare_type %}{{ destination }}: {{ property.get_type_string(json=True) }}{% endif %}
45
45
 
46
- {% if not property.required %}
46
+ {% if not property.required and not skip_unset %}
47
47
  if isinstance({{ source }}, Unset):
48
48
  {{ destination }} = UNSET
49
49
  {% set ns.has_if = true %}
@@ -10,16 +10,18 @@ UUID({{ source }})
10
10
 
11
11
  {% macro check_type_for_construct(property, source) %}isinstance({{ source }}, str){% endmacro %}
12
12
 
13
- {% macro transform(property, source, destination, declare_type=True) %}
13
+ {% macro transform(property, source, destination, declare_type=True, skip_unset=False) %}
14
14
  {% set transformed = "str(" + source + ")" %}
15
15
  {% if property.required %}
16
16
  {{ destination }} = {{ transformed }}
17
17
  {%- else %}
18
- {% if declare_type %}
19
- {% set type_annotation = property.get_type_string(json=True) %}
18
+ {% if not skip_unset %}
19
+ {% if declare_type %}
20
+ {% set type_annotation = property.get_type_string(json=True) %}
20
21
  {{ destination }}: {{ type_annotation }} = UNSET
21
- {% else %}
22
+ {% else %}
22
23
  {{ destination }} = UNSET
24
+ {% endif %}
23
25
  {% endif %}
24
26
  if not isinstance({{ source }}, Unset):
25
27
  {{ destination }} = {{ transformed }}
@@ -27,5 +29,5 @@ if not isinstance({{ source }}, Unset):
27
29
  {% endmacro %}
28
30
 
29
31
  {% macro multipart(property, source, name) %}
30
- files.append(({{ name }}, (None, str({{ source }}), "text/plain"))
32
+ files.append(({{ name }}, (None, str({{ source }}), "text/plain")))
31
33
  {% endmacro %}
@@ -6,18 +6,18 @@ license = { text = "MIT" }
6
6
  requires-python = ">=3.10,<4.0"
7
7
  dependencies = [
8
8
  "jinja2>=3.0.0,<4.0.0",
9
- "typer>0.16,<0.21",
9
+ "typer>0.16,<0.22",
10
10
  "colorama>=0.4.3; sys_platform == \"win32\"",
11
11
  "shellingham>=1.3.2,<2.0.0",
12
12
  "pydantic>=2.10,<3.0.0",
13
13
  "attrs>=22.2.0",
14
14
  "python-dateutil>=2.8.1,<3.0.0",
15
15
  "httpx>=0.23.0,<0.29.0",
16
- "ruamel.yaml>=0.18.6,<0.19.0",
16
+ "ruamel.yaml>=0.18.6,<0.20.0",
17
17
  "ruff>=0.2",
18
18
  ]
19
19
  name = "openapi-python-client"
20
- version = "0.27.1"
20
+ version = "0.28.1"
21
21
  description = "Generate modern Python clients from OpenAPI"
22
22
  keywords = [
23
23
  "OpenAPI",