openapi-python-client 0.27.0__tar.gz → 0.28.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 (113) hide show
  1. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/PKG-INFO +1 -1
  2. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/parser/bodies.py +1 -1
  3. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/parser/properties/union.py +14 -9
  4. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/client.py.jinja +2 -2
  5. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/endpoint_macros.py.jinja +19 -6
  6. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/endpoint_module.py.jinja +3 -2
  7. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/model.py.jinja +3 -0
  8. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/property_templates/date_property.py.jinja +6 -4
  9. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/property_templates/datetime_property.py.jinja +7 -5
  10. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/property_templates/enum_property.py.jinja +2 -2
  11. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/property_templates/file_property.py.jinja +2 -2
  12. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/property_templates/list_property.py.jinja +12 -6
  13. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/property_templates/literal_enum_property.py.jinja +2 -2
  14. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/property_templates/model_property.py.jinja +3 -2
  15. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/property_templates/union_property.py.jinja +3 -3
  16. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/property_templates/uuid_property.py.jinja +7 -5
  17. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/pyproject_poetry.toml.jinja +1 -1
  18. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/pyproject_uv.toml.jinja +1 -4
  19. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/pyproject.toml +1 -1
  20. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/.gitignore +0 -0
  21. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/LICENSE +0 -0
  22. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/README.md +0 -0
  23. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/__init__.py +0 -0
  24. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/__main__.py +0 -0
  25. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/cli.py +0 -0
  26. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/config.py +0 -0
  27. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/parser/__init__.py +0 -0
  28. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/parser/errors.py +0 -0
  29. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/parser/openapi.py +0 -0
  30. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/parser/properties/__init__.py +0 -0
  31. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/parser/properties/any.py +0 -0
  32. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/parser/properties/boolean.py +0 -0
  33. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/parser/properties/const.py +0 -0
  34. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/parser/properties/date.py +0 -0
  35. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/parser/properties/datetime.py +0 -0
  36. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/parser/properties/enum_property.py +0 -0
  37. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/parser/properties/file.py +0 -0
  38. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/parser/properties/float.py +0 -0
  39. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/parser/properties/int.py +0 -0
  40. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/parser/properties/list_property.py +0 -0
  41. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/parser/properties/literal_enum_property.py +0 -0
  42. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/parser/properties/merge_properties.py +0 -0
  43. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/parser/properties/model_property.py +0 -0
  44. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/parser/properties/none.py +0 -0
  45. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/parser/properties/property.py +0 -0
  46. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/parser/properties/protocol.py +0 -0
  47. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/parser/properties/schemas.py +0 -0
  48. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/parser/properties/string.py +0 -0
  49. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/parser/properties/uuid.py +0 -0
  50. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/parser/responses.py +0 -0
  51. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/py.typed +0 -0
  52. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/3.0.3.md +0 -0
  53. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/3.1.0.md +0 -0
  54. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/__init__.py +0 -0
  55. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/data_type.py +0 -0
  56. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/LICENSE +0 -0
  57. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/README.md +0 -0
  58. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/__init__.py +0 -0
  59. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/callback.py +0 -0
  60. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/components.py +0 -0
  61. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/contact.py +0 -0
  62. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/discriminator.py +0 -0
  63. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/encoding.py +0 -0
  64. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/example.py +0 -0
  65. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/external_documentation.py +0 -0
  66. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/header.py +0 -0
  67. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/info.py +0 -0
  68. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/license.py +0 -0
  69. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/link.py +0 -0
  70. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/media_type.py +0 -0
  71. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/oauth_flow.py +0 -0
  72. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/oauth_flows.py +0 -0
  73. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/open_api.py +0 -0
  74. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/operation.py +0 -0
  75. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/parameter.py +0 -0
  76. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/path_item.py +0 -0
  77. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/paths.py +0 -0
  78. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/reference.py +0 -0
  79. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/request_body.py +0 -0
  80. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/response.py +0 -0
  81. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/responses.py +0 -0
  82. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/schema.py +0 -0
  83. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/security_requirement.py +0 -0
  84. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/security_scheme.py +0 -0
  85. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/server.py +0 -0
  86. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/server_variable.py +0 -0
  87. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/tag.py +0 -0
  88. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/openapi_schema_pydantic/xml.py +0 -0
  89. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/schema/parameter_location.py +0 -0
  90. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/.gitignore.jinja +0 -0
  91. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/README.md.jinja +0 -0
  92. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/api_init.py.jinja +0 -0
  93. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/endpoint_init.py.jinja +0 -0
  94. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/errors.py.jinja +0 -0
  95. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/helpers.jinja +0 -0
  96. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/int_enum.py.jinja +0 -0
  97. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/literal_enum.py.jinja +0 -0
  98. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/models_init.py.jinja +0 -0
  99. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/package_init.py.jinja +0 -0
  100. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/property_templates/any_property.py.jinja +0 -0
  101. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/property_templates/boolean_property.py.jinja +0 -0
  102. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/property_templates/const_property.py.jinja +0 -0
  103. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/property_templates/float_property.py.jinja +0 -0
  104. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/property_templates/helpers.jinja +0 -0
  105. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/property_templates/int_property.py.jinja +0 -0
  106. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/property_templates/property_macros.py.jinja +0 -0
  107. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/pyproject.toml.jinja +0 -0
  108. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/pyproject_pdm.toml.jinja +0 -0
  109. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/pyproject_ruff.toml.jinja +0 -0
  110. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/setup.py.jinja +0 -0
  111. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/str_enum.py.jinja +0 -0
  112. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/openapi_python_client/templates/types.py.jinja +0 -0
  113. {openapi_python_client-0.27.0 → openapi_python_client-0.28.0}/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.0
3
+ Version: 0.28.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>
@@ -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,
@@ -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,
@@ -90,7 +90,7 @@ class Client:
90
90
  return evolve(self, cookies={**self._cookies, **cookies})
91
91
 
92
92
  def with_timeout(self, timeout: httpx.Timeout) -> "{{ self }}":
93
- """Get a new client matching this one with a new timeout (in seconds)"""
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
96
96
  if self._async_client is not None:
@@ -133,7 +133,7 @@ class Client:
133
133
  self.get_httpx_client().__exit__(*args, **kwargs)
134
134
 
135
135
  def set_async_httpx_client(self, async_client: httpx.AsyncClient) -> "{{ name }}":
136
- """Manually the underlying httpx.AsyncClient
136
+ """Manually set the underlying httpx.AsyncClient
137
137
 
138
138
  **NOTE**: This will override any other settings on the client, including cookies, headers, and timeout.
139
139
  """
@@ -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 %}
@@ -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 %}
@@ -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 %}
@@ -3,16 +3,22 @@
3
3
  {% import "property_templates/" + inner_property.template as inner_template %}
4
4
  {% if inner_template.construct %}
5
5
  {% set inner_source = inner_property.python_name + "_data" %}
6
+ {% if property.required %}
6
7
  {{ property.python_name }} = []
7
8
  _{{ property.python_name }} = {{ source }}
8
- {% if property.required %}
9
9
  for {{ inner_source }} in (_{{ property.python_name }}):
10
- {% else %}
11
- for {{ inner_source }} in (_{{ property.python_name }} or []):
12
- {% endif %}
13
10
  {{ inner_template.construct(inner_property, inner_source) | indent(4) }}
14
11
  {{ property.python_name }}.append({{ inner_property.python_name }})
15
12
  {% else %}
13
+ _{{ property.python_name }} = {{ source }}
14
+ {{ property.python_name }}: {{ property.get_type_string() }} = UNSET
15
+ if _{{ property.python_name }} is not UNSET:
16
+ {{ property.python_name }} = []
17
+ for {{ inner_source }} in _{{ property.python_name }}:
18
+ {{ inner_template.construct(inner_property, inner_source) | indent(8) }}
19
+ {{ property.python_name }}.append({{ inner_property.python_name }})
20
+ {% endif %}
21
+ {% else %}
16
22
  {{ property.python_name }} = cast({{ property.get_type_string(no_optional=True) }}, {{ source }})
17
23
  {% endif %}
18
24
  {% endmacro %}
@@ -33,13 +39,13 @@ for {{ inner_source }} in {{ source }}:
33
39
 
34
40
  {% macro check_type_for_construct(property, source) %}isinstance({{ source }}, list){% endmacro %}
35
41
 
36
- {% macro transform(property, source, destination, declare_type=True) %}
42
+ {% macro transform(property, source, destination, declare_type=True, skip_unset=False) %}
37
43
  {% set inner_property = property.inner_property %}
38
44
  {% set type_string = property.get_type_string(json=True) %}
39
45
  {% if property.required %}
40
46
  {{ _transform(property, source, destination, "to_dict") }}
41
47
  {% else %}
42
- {{ destination }}{% if declare_type %}: {{ type_string }}{% endif %} = UNSET
48
+ {% if not skip_unset %}{{ destination }}{% if declare_type %}: {{ type_string }}{% endif %} = UNSET{% endif +%}
43
49
  if not isinstance({{ source }}, Unset):
44
50
  {{ _transform(property, source, destination, "to_dict") | indent(4)}}
45
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 %}
@@ -21,7 +21,7 @@ def _parse_{{ property.python_name }}(data: object) -> {{ property.get_type_stri
21
21
  raise TypeError()
22
22
  {{ inner_template.construct(inner_property, "data") | indent(8) }}
23
23
  return {{ inner_property.python_name }}
24
- except: # noqa: E722
24
+ except (TypeError, ValueError, AttributeError, KeyError):
25
25
  pass
26
26
  {% else %}{# Don't do try/except for the last one nor any properties with no type checking #}
27
27
  {% if inner_template.check_type_for_construct %}
@@ -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 %}
@@ -7,7 +7,7 @@ readme = "README.md"
7
7
  packages = [
8
8
  { include = "{{ package_name }}" },
9
9
  ]
10
- include = ["CHANGELOG.md", "{{ package_name }}/py.typed"]
10
+ include = ["{{ package_name }}/py.typed"]
11
11
 
12
12
  [tool.poetry.dependencies]
13
13
  python = "^3.10"
@@ -14,10 +14,7 @@ dependencies = [
14
14
  [tool.uv.build-backend]
15
15
  module-name = "{{ package_name }}"
16
16
  module-root = ""
17
- data = [
18
- "CHANGELOG.md",
19
- ]
20
17
 
21
18
  [build-system]
22
- requires = ["uv_build>=0.8.0,<0.9.0"]
19
+ requires = ["uv_build>=0.9.0,<0.10.0"]
23
20
  build-backend = "uv_build"
@@ -17,7 +17,7 @@ dependencies = [
17
17
  "ruff>=0.2",
18
18
  ]
19
19
  name = "openapi-python-client"
20
- version = "0.27.0"
20
+ version = "0.28.0"
21
21
  description = "Generate modern Python clients from OpenAPI"
22
22
  keywords = [
23
23
  "OpenAPI",