Skip to content

Commit 9f2b80e

Browse files
authored
fix: python pydantic unwrap properties (#2111)
1 parent f4976c9 commit 9f2b80e

File tree

3 files changed

+31
-24
lines changed

3 files changed

+31
-24
lines changed

examples/generate-python-pydantic-models/__snapshots__/index.spec.ts.snap

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
exports[`Should be able to render python models and should log expected output to console: class-model 1`] = `
44
Array [
55
"class Root(BaseModel):
6-
optional_field: Optional[str] = Field(description='''this field is optional''', default=None, alias='''optionalField''')
7-
required_field: str = Field(description='''this field is required''', alias='''requiredField''')
8-
no_description: Optional[str] = Field(default=None, alias='''noDescription''')
6+
optional_field: Optional[str] = Field(description='''this field is optional''', default=None)
7+
required_field: str = Field(description='''this field is required''')
8+
no_description: Optional[str] = Field(default=None)
99
options: Optional[Options.Options] = Field(default=None)
10-
content_type: Optional[str] = Field(default=None, alias='''content-type''')
10+
content_type: Optional[str] = Field(default=None)
1111
",
1212
]
1313
`;

src/generators/python/presets/Pydantic.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,6 @@ const PYTHON_PYDANTIC_CLASS_PRESET: ClassPresetType<PythonOptions> = {
5757
if (!property.required) {
5858
decoratorArgs.push('default=None');
5959
}
60-
if (property.propertyName !== property.unconstrainedPropertyName) {
61-
decoratorArgs.push(`alias='''${property.unconstrainedPropertyName}'''`);
62-
}
6360

6461
return `${propertyName}: ${type} = Field(${decoratorArgs.join(', ')})`;
6562
},
@@ -101,6 +98,8 @@ def custom_serializer(self, handler):
10198
@model_validator(mode='before')
10299
@classmethod
103100
def unwrap_${dictionaryModel?.propertyName}(cls, data):
101+
if not isinstance(data, dict):
102+
data = data.model_dump()
104103
json_properties = list(data.keys())
105104
known_object_properties = [${allProperties
106105
.map((value) => `'${value}'`)
@@ -113,11 +112,11 @@ def unwrap_${dictionaryModel?.propertyName}(cls, data):
113112
known_json_properties = [${Object.values(model.properties)
114113
.map((value) => `'${value.unconstrainedPropertyName}'`)
115114
.join(', ')}]
116-
${dictionaryModel?.propertyName} = {}
115+
${dictionaryModel?.propertyName} = data.get('${dictionaryModel?.propertyName}', {})
117116
for obj_key in list(data.keys()):
118117
if not known_json_properties.__contains__(obj_key):
119118
${dictionaryModel?.propertyName}[obj_key] = data.pop(obj_key, None)
120-
data['${dictionaryModel?.unconstrainedPropertyName}'] = ${dictionaryModel?.propertyName}
119+
data['${dictionaryModel?.propertyName}'] = ${dictionaryModel?.propertyName}
121120
return data
122121
${content}`;
123122
}

test/generators/python/presets/__snapshots__/Pydantic.spec.ts.snap

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ exports[`PYTHON_PYDANTIC_PRESET should render pydantic for class 1`] = `
66
multi
77
line
88
description''', default=None)
9-
additional_properties: Optional[dict[str, Any]] = Field(exclude=True, default=None, alias='''additionalProperties''')
9+
additional_properties: Optional[dict[str, Any]] = Field(exclude=True, default=None)
1010
1111
@model_serializer(mode='wrap')
1212
def custom_serializer(self, handler):
@@ -23,6 +23,8 @@ exports[`PYTHON_PYDANTIC_PRESET should render pydantic for class 1`] = `
2323
@model_validator(mode='before')
2424
@classmethod
2525
def unwrap_additional_properties(cls, data):
26+
if not isinstance(data, dict):
27+
data = data.model_dump()
2628
json_properties = list(data.keys())
2729
known_object_properties = ['prop', 'additional_properties']
2830
unknown_object_properties = [element for element in json_properties if element not in known_object_properties]
@@ -31,11 +33,11 @@ exports[`PYTHON_PYDANTIC_PRESET should render pydantic for class 1`] = `
3133
return data
3234
3335
known_json_properties = ['prop', 'additionalProperties']
34-
additional_properties = {}
36+
additional_properties = data.get('additional_properties', {})
3537
for obj_key in list(data.keys()):
3638
if not known_json_properties.__contains__(obj_key):
3739
additional_properties[obj_key] = data.pop(obj_key, None)
38-
data['additionalProperties'] = additional_properties
40+
data['additional_properties'] = additional_properties
3941
return data
4042
4143
"
@@ -44,8 +46,8 @@ exports[`PYTHON_PYDANTIC_PRESET should render pydantic for class 1`] = `
4446
exports[`PYTHON_PYDANTIC_PRESET should render union to support Python < 3.10 1`] = `
4547
Array [
4648
"class UnionTest(BaseModel):
47-
union_test: Optional[Union[Union1.Union1, Union2.Union2]] = Field(default=None, alias='''unionTest''')
48-
additional_properties: Optional[dict[str, Any]] = Field(exclude=True, default=None, alias='''additionalProperties''')
49+
union_test: Optional[Union[Union1.Union1, Union2.Union2]] = Field(default=None)
50+
additional_properties: Optional[dict[str, Any]] = Field(exclude=True, default=None)
4951
5052
@model_serializer(mode='wrap')
5153
def custom_serializer(self, handler):
@@ -62,6 +64,8 @@ Array [
6264
@model_validator(mode='before')
6365
@classmethod
6466
def unwrap_additional_properties(cls, data):
67+
if not isinstance(data, dict):
68+
data = data.model_dump()
6569
json_properties = list(data.keys())
6670
known_object_properties = ['union_test', 'additional_properties']
6771
unknown_object_properties = [element for element in json_properties if element not in known_object_properties]
@@ -70,17 +74,17 @@ Array [
7074
return data
7175
7276
known_json_properties = ['unionTest', 'additionalProperties']
73-
additional_properties = {}
77+
additional_properties = data.get('additional_properties', {})
7478
for obj_key in list(data.keys()):
7579
if not known_json_properties.__contains__(obj_key):
7680
additional_properties[obj_key] = data.pop(obj_key, None)
77-
data['additionalProperties'] = additional_properties
81+
data['additional_properties'] = additional_properties
7882
return data
7983
8084
",
8185
"class Union1(BaseModel):
82-
test_prop1: Optional[str] = Field(default=None, alias='''testProp1''')
83-
additional_properties: Optional[dict[str, Any]] = Field(exclude=True, default=None, alias='''additionalProperties''')
86+
test_prop1: Optional[str] = Field(default=None)
87+
additional_properties: Optional[dict[str, Any]] = Field(exclude=True, default=None)
8488
8589
@model_serializer(mode='wrap')
8690
def custom_serializer(self, handler):
@@ -97,6 +101,8 @@ Array [
97101
@model_validator(mode='before')
98102
@classmethod
99103
def unwrap_additional_properties(cls, data):
104+
if not isinstance(data, dict):
105+
data = data.model_dump()
100106
json_properties = list(data.keys())
101107
known_object_properties = ['test_prop1', 'additional_properties']
102108
unknown_object_properties = [element for element in json_properties if element not in known_object_properties]
@@ -105,17 +111,17 @@ Array [
105111
return data
106112
107113
known_json_properties = ['testProp1', 'additionalProperties']
108-
additional_properties = {}
114+
additional_properties = data.get('additional_properties', {})
109115
for obj_key in list(data.keys()):
110116
if not known_json_properties.__contains__(obj_key):
111117
additional_properties[obj_key] = data.pop(obj_key, None)
112-
data['additionalProperties'] = additional_properties
118+
data['additional_properties'] = additional_properties
113119
return data
114120
115121
",
116122
"class Union2(BaseModel):
117-
test_prop2: Optional[str] = Field(default=None, alias='''testProp2''')
118-
additional_properties: Optional[dict[str, Any]] = Field(exclude=True, default=None, alias='''additionalProperties''')
123+
test_prop2: Optional[str] = Field(default=None)
124+
additional_properties: Optional[dict[str, Any]] = Field(exclude=True, default=None)
119125
120126
@model_serializer(mode='wrap')
121127
def custom_serializer(self, handler):
@@ -132,6 +138,8 @@ Array [
132138
@model_validator(mode='before')
133139
@classmethod
134140
def unwrap_additional_properties(cls, data):
141+
if not isinstance(data, dict):
142+
data = data.model_dump()
135143
json_properties = list(data.keys())
136144
known_object_properties = ['test_prop2', 'additional_properties']
137145
unknown_object_properties = [element for element in json_properties if element not in known_object_properties]
@@ -140,11 +148,11 @@ Array [
140148
return data
141149
142150
known_json_properties = ['testProp2', 'additionalProperties']
143-
additional_properties = {}
151+
additional_properties = data.get('additional_properties', {})
144152
for obj_key in list(data.keys()):
145153
if not known_json_properties.__contains__(obj_key):
146154
additional_properties[obj_key] = data.pop(obj_key, None)
147-
data['additionalProperties'] = additional_properties
155+
data['additional_properties'] = additional_properties
148156
return data
149157
150158
",

0 commit comments

Comments
 (0)