Skip to content

Commit 0b9a99a

Browse files
fix: Fix bug parsing allOf in nested keys BNCH-20174 (#29)
1 parent ce30b4c commit 0b9a99a

File tree

2 files changed

+79
-7
lines changed

2 files changed

+79
-7
lines changed

openapi_python_client/parser/properties/__init__.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -268,9 +268,6 @@ def build_model_property(
268268

269269
for key, value in all_props.items():
270270
prop_required = key in required_set
271-
if not isinstance(value, oai.Reference) and value.allOf:
272-
# resolved later
273-
continue
274271
prop, schemas = property_from_data(
275272
name=key, required=prop_required, data=value, schemas=schemas, parent_name=class_name
276273
)
@@ -463,9 +460,6 @@ def _property_from_data(
463460
)
464461
if data.anyOf or data.oneOf:
465462
return build_union_property(data=data, name=name, required=required, schemas=schemas, parent_name=parent_name)
466-
if not data.type:
467-
return NoneProperty(name=name, required=required, nullable=False, default=None), schemas
468-
469463
if data.type == "string":
470464
return _string_based_property(name=name, required=required, data=data), schemas
471465
elif data.type == "number":
@@ -500,8 +494,10 @@ def _property_from_data(
500494
)
501495
elif data.type == "array":
502496
return build_list_property(data=data, name=name, required=required, schemas=schemas, parent_name=parent_name)
503-
elif data.type == "object":
497+
elif data.type == "object" or data.allOf:
504498
return build_model_property(data=data, name=name, schemas=schemas, required=required, parent_name=parent_name)
499+
elif not data.type:
500+
return NoneProperty(name=name, required=required, nullable=False, default=None), schemas
505501
return PropertyError(data=data, detail=f"unknown type {data.type}"), schemas
506502

507503

tests/test_parser/test_properties/test_model_property.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,79 @@ def test_resolve_references(mocker):
123123
assert all(p.required for p in model.required_properties)
124124
assert sorted(p.name for p in model.optional_properties) == ["Enum", "Int"]
125125
assert all(not p.required for p in model.optional_properties)
126+
127+
128+
def test_resolve_references_nested_allof(mocker):
129+
import openapi_python_client.schema as oai
130+
from openapi_python_client.parser.properties import build_model_property
131+
132+
schemas = {
133+
"RefA": oai.Schema.construct(
134+
title=mocker.MagicMock(),
135+
description=mocker.MagicMock(),
136+
required=["String"],
137+
properties={
138+
"String": oai.Schema.construct(type="string"),
139+
"Enum": oai.Schema.construct(type="string", enum=["aValue"]),
140+
"DateTime": oai.Schema.construct(type="string", format="date-time"),
141+
},
142+
),
143+
"RefB": oai.Schema.construct(
144+
title=mocker.MagicMock(),
145+
description=mocker.MagicMock(),
146+
required=["DateTime"],
147+
properties={
148+
"Int": oai.Schema.construct(type="integer"),
149+
"DateTime": oai.Schema.construct(type="string", format="date-time"),
150+
"Float": oai.Schema.construct(type="number", format="float"),
151+
},
152+
),
153+
# Intentionally no properties defined
154+
"RefC": oai.Schema.construct(
155+
title=mocker.MagicMock(),
156+
description=mocker.MagicMock(),
157+
),
158+
}
159+
160+
model_schema = oai.Schema.construct(
161+
type="object",
162+
properties={
163+
"Key": oai.Schema.construct(
164+
allOf=[
165+
oai.Reference.construct(ref="#/components/schemas/RefA"),
166+
oai.Reference.construct(ref="#/components/schemas/RefB"),
167+
oai.Reference.construct(ref="#/components/schemas/RefC"),
168+
oai.Schema.construct(
169+
title=mocker.MagicMock(),
170+
description=mocker.MagicMock(),
171+
required=["Float"],
172+
properties={
173+
"String": oai.Schema.construct(type="string"),
174+
"Float": oai.Schema.construct(type="number", format="float"),
175+
},
176+
),
177+
]
178+
),
179+
}
180+
)
181+
182+
components = {**schemas, "Model": model_schema}
183+
184+
from openapi_python_client.parser.properties import ModelProperty, Schemas
185+
186+
schemas_holder = Schemas()
187+
model, schemas_holder = build_model_property(
188+
data=model_schema, name="Model", required=True, schemas=schemas_holder, parent_name=None
189+
)
190+
model.resolve_references(components, schemas_holder)
191+
assert sorted(p.name for p in model.required_properties) == []
192+
assert sorted(p.name for p in model.optional_properties) == ["Key"]
193+
assert all(not p.required for p in model.optional_properties)
194+
195+
key_property = model.optional_properties[0]
196+
assert isinstance(key_property, ModelProperty)
197+
key_property.resolve_references(components, schemas_holder)
198+
assert sorted(p.name for p in key_property.required_properties) == ["DateTime", "Float", "String"]
199+
assert all(p.required for p in key_property.required_properties)
200+
assert sorted(p.name for p in key_property.optional_properties) == ["Enum", "Int"]
201+
assert all(not p.required for p in key_property.optional_properties)

0 commit comments

Comments
 (0)