Skip to content

Commit 98a5aa1

Browse files
committed
Remove support for defaults in lists/dicts. Closes #170
1 parent ac65697 commit 98a5aa1

File tree

5 files changed

+21
-64
lines changed

5 files changed

+21
-64
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## 0.6.0 - Unreleased
8+
### Breaking Changes
9+
- Reorganized api calls in generated clients. `async_api` will no longer be generated. Each path operation will now
10+
have it's own module under its tag. For example, if there was a generated function `api.my_tag.my_function()` it is
11+
replaced with `api.my_tag.my_function.sync()`. The async version can be called with `asyncio()` instead of `sync()`.
12+
- Removed support for mutable default values (e.g. dicts, lists). They may be added back in a future version given enough
13+
demand, but the existing implementation was not up to this project's standards.
14+
715

816
## 0.5.4 - Unreleased
917
### Additions

end_to_end_tests/golden-master/my_test_api_client/api/tests/test_defaults_tests_test_defaults_post.py

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import datetime
2-
from dataclasses import asdict, field
2+
from dataclasses import asdict
33
from typing import Any, Dict, List, Optional, Union, cast
44

55
import httpx
@@ -20,9 +20,7 @@ def _get_kwargs(
2020
float_prop: Optional[float] = 3.14,
2121
int_prop: Optional[int] = 7,
2222
boolean_prop: Optional[bool] = False,
23-
list_prop: Optional[List[AnEnum]] = field(
24-
default_factory=lambda: cast(Optional[List[AnEnum]], [AnEnum.FIRST_VALUE, AnEnum.SECOND_VALUE])
25-
),
23+
list_prop: Optional[List[AnEnum]] = None,
2624
union_prop: Optional[Union[Optional[float], Optional[str]]] = "not a float",
2725
enum_prop: Optional[AnEnum] = None,
2826
) -> Dict[str, Any]:
@@ -105,9 +103,7 @@ def sync(
105103
float_prop: Optional[float] = 3.14,
106104
int_prop: Optional[int] = 7,
107105
boolean_prop: Optional[bool] = False,
108-
list_prop: Optional[List[AnEnum]] = field(
109-
default_factory=lambda: cast(Optional[List[AnEnum]], [AnEnum.FIRST_VALUE, AnEnum.SECOND_VALUE])
110-
),
106+
list_prop: Optional[List[AnEnum]] = None,
111107
union_prop: Optional[Union[Optional[float], Optional[str]]] = "not a float",
112108
enum_prop: Optional[AnEnum] = None,
113109
) -> Union[
@@ -144,9 +140,7 @@ async def asyncio(
144140
float_prop: Optional[float] = 3.14,
145141
int_prop: Optional[int] = 7,
146142
boolean_prop: Optional[bool] = False,
147-
list_prop: Optional[List[AnEnum]] = field(
148-
default_factory=lambda: cast(Optional[List[AnEnum]], [AnEnum.FIRST_VALUE, AnEnum.SECOND_VALUE])
149-
),
143+
list_prop: Optional[List[AnEnum]] = None,
150144
union_prop: Optional[Union[Optional[float], Optional[str]]] = "not a float",
151145
enum_prop: Optional[AnEnum] = None,
152146
) -> Union[

end_to_end_tests/golden-master/my_test_api_client/models/a_model.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22

33
import datetime
4-
from dataclasses import dataclass, field
4+
from dataclasses import dataclass
55
from typing import Any, Dict, List, Optional, Union, cast
66

77
from .an_enum import AnEnum
@@ -16,9 +16,7 @@ class AModel:
1616
some_dict: Dict[Any, Any]
1717
a_camel_date_time: Union[datetime.datetime, datetime.date]
1818
a_date: datetime.date
19-
nested_list_of_enums: Optional[List[List[DifferentEnum]]] = field(
20-
default_factory=lambda: cast(Optional[List[List[DifferentEnum]]], [])
21-
)
19+
nested_list_of_enums: Optional[List[List[DifferentEnum]]] = None
2220

2321
def to_dict(self) -> Dict[str, Any]:
2422
an_enum_value = self.an_enum_value.value

openapi_python_client/parser/properties.py

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -233,20 +233,10 @@ def get_imports(self, *, prefix: str) -> Set[str]:
233233
imports = super().get_imports(prefix=prefix)
234234
imports.update(self.inner_property.get_imports(prefix=prefix))
235235
imports.add("from typing import List")
236-
if self.default is not None:
237-
imports.add("from dataclasses import field")
238-
imports.add("from typing import cast")
239236
return imports
240237

241-
def _validate_default(self, default: Any) -> str:
242-
if not isinstance(default, list):
243-
raise ValidationError()
244-
245-
default = list(map(self.inner_property._validate_default, default))
246-
if isinstance(self.inner_property, RefProperty): # Fix enums to use the actual value
247-
default = str(default).replace("'", "")
248-
249-
return f"field(default_factory=lambda: cast({self.get_type_string()}, {default}))"
238+
def _validate_default(self, default: Any) -> None:
239+
return None
250240

251241

252242
@dataclass
@@ -432,10 +422,8 @@ def get_imports(self, *, prefix: str) -> Set[str]:
432422
imports.add("from typing import cast")
433423
return imports
434424

435-
def _validate_default(self, default: Any) -> str:
436-
if isinstance(default, dict):
437-
return repr(default)
438-
raise ValidationError
425+
def _validate_default(self, default: Any) -> None:
426+
return None
439427

440428

441429
def _string_based_property(

tests/test_openapi_parser/test_properties.py

Lines changed: 3 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -226,9 +226,6 @@ def test_get_type_string(self, mocker):
226226
p.required = False
227227
assert p.get_type_string() == f"Optional[List[{inner_type_string}]]"
228228

229-
p = ListProperty(name="test", required=True, default=[], inner_property=inner_property, nullable=False)
230-
assert p.default == f"field(default_factory=lambda: cast(List[{inner_type_string}], []))"
231-
232229
def test_get_type_imports(self, mocker):
233230
from openapi_python_client.parser.properties import ListProperty
234231

@@ -249,40 +246,13 @@ def test_get_type_imports(self, mocker):
249246
"from typing import Optional",
250247
}
251248

252-
p.default = mocker.MagicMock()
253-
assert p.get_imports(prefix=prefix) == {
254-
inner_import,
255-
"from typing import Optional",
256-
"from typing import List",
257-
"from typing import cast",
258-
"from dataclasses import field",
259-
}
260-
261249
def test__validate_default(self, mocker):
262250
from openapi_python_client.parser.properties import ListProperty
263251

264252
inner_property = mocker.MagicMock()
265-
inner_type_string = mocker.MagicMock()
266-
inner_property.get_type_string.return_value = inner_type_string
267-
inner_property._validate_default.return_value = "y"
268253

269254
p = ListProperty(name="a name", required=True, default=["x"], inner_property=inner_property, nullable=False)
270-
assert p.default == f"field(default_factory=lambda: cast(List[{inner_type_string}], ['y']))"
271-
272-
with pytest.raises(ValidationError):
273-
ListProperty(name="a name", required=True, default="x", inner_property=inner_property, nullable=False)
274-
275-
def test__validate_default_enum_items(self, mocker):
276-
from openapi_python_client.parser.properties import ListProperty, RefProperty
277-
278-
inner_enum_property = mocker.MagicMock(spec=RefProperty)
279-
inner_enum_property.get_type_string.return_value = "AnEnum"
280-
inner_enum_property._validate_default.return_value = "AnEnum.val1"
281-
282-
p = ListProperty(
283-
name="a name", required=True, default=["val1"], inner_property=inner_enum_property, nullable=False
284-
)
285-
assert p.default == "field(default_factory=lambda: cast(List[AnEnum], [AnEnum.val1]))"
255+
assert p.default is None
286256

287257

288258
class TestUnionProperty:
@@ -607,10 +577,9 @@ def test_get_imports(self, mocker):
607577
def test__validate_default(self):
608578
from openapi_python_client.parser.properties import DictProperty
609579

610-
DictProperty(name="a name", required=True, default={"key": "value"}, nullable=False)
580+
p = DictProperty(name="a name", required=True, default={"key": "value"}, nullable=False)
611581

612-
with pytest.raises(ValidationError):
613-
DictProperty(name="a name", required=True, default="not a dict", nullable=False)
582+
assert p.default is None
614583

615584

616585
class TestPropertyFromData:

0 commit comments

Comments
 (0)