Skip to content

Commit 3379183

Browse files
authored
Fix msgspec mutable default values to use default_factory (#2666)
* Fix handling of mutable default values in msgspec to ensure safety * Fix handling of default values in msgspec to support empty defaults and improve factory assignment
1 parent 502f80a commit 3379183

4 files changed

Lines changed: 32 additions & 1 deletion

File tree

src/datamodel_code_generator/model/msgspec.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,13 @@ def __str__(self) -> str:
274274
data.pop("default")
275275
data["default_factory"] = default_factory
276276

277+
if "default" in data and isinstance(data["default"], (list, dict, set)) and "default_factory" not in data:
278+
default_value = data.pop("default")
279+
if default_value:
280+
data["default_factory"] = f"lambda: {default_value!r}"
281+
else:
282+
data["default_factory"] = type(default_value).__name__
283+
277284
if not data:
278285
return ""
279286

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# generated by datamodel-codegen:
2+
# filename: empty_dict_default.yaml
3+
# timestamp: 2019-07-26T00:00:00+00:00
4+
5+
from __future__ import annotations
6+
7+
from typing import Union
8+
9+
from msgspec import UNSET, Struct, UnsetType, field
10+
11+
12+
class ObjectMeta(Struct):
13+
name: Union[str, UnsetType] = UNSET
14+
namespace: Union[str, UnsetType] = UNSET
15+
16+
17+
class PodSpec(Struct):
18+
metadata: Union[ObjectMeta, UnsetType] = field(default_factory=dict)

tests/data/expected/main/openapi/msgspec_union_default_object.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,6 @@ class Container(Struct):
1919
default_factory=lambda: convert({'start': 2009, 'end': 2019}, type=Interval)
2020
)
2121
string_or_interval: Union[Interval, str, UnsetType] = 'some string value'
22-
dict_or_interval: Union[Dict[str, str], Interval, UnsetType] = {'key': 'value'}
22+
dict_or_interval: Union[Dict[str, str], Interval, UnsetType] = field(
23+
default_factory=lambda: {'key': 'value'}
24+
)

tests/main/openapi/test_main_openapi.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1928,6 +1928,10 @@ def test_main_openapi_union_default_object(output_model: str, expected_output: s
19281928
"pydantic_v2.BaseModel",
19291929
"pydantic_v2_empty_dict_default.py",
19301930
),
1931+
(
1932+
"msgspec.Struct",
1933+
"msgspec_empty_dict_default.py",
1934+
),
19311935
],
19321936
)
19331937
@pytest.mark.skipif(

0 commit comments

Comments
 (0)