2020from openapi_python_generator .models import Model
2121from openapi_python_generator .models import Property
2222from openapi_python_generator .models import TypeConversion
23+ from openapi_python_generator .models import ParentModel
2324
2425
2526def type_converter ( # noqa: C901
@@ -281,6 +282,32 @@ def _generate_property_from_reference(
281282 import_type = [import_model ],
282283 )
283284
285+ def _generate_property (
286+ model_name : str ,
287+ name : str ,
288+ schema_or_reference : Schema | Reference ,
289+ parent_schema : Optional [Schema ] = None ,
290+ ) -> Property :
291+ if isinstance (schema_or_reference , Reference ):
292+ return _generate_property_from_reference (
293+ model_name , name , schema_or_reference , parent_schema
294+ )
295+
296+ return _generate_property_from_schema (
297+ model_name , name , schema_or_reference , parent_schema
298+ )
299+
300+ def _collect_properties_from_schema (model_name : str , parent_schema : Schema ):
301+ property_iterator = (
302+ parent_schema .properties .items ()
303+ if parent_schema .properties is not None
304+ else {}
305+ )
306+ for name , schema_or_reference in property_iterator :
307+ conv_property = _generate_property (
308+ model_name , name , schema_or_reference , parent_schema
309+ )
310+ yield conv_property
284311
285312def generate_models (components : Components , pydantic_version : PydanticVersion = PydanticVersion .V2 ) -> List [Model ]:
286313 """
@@ -323,27 +350,39 @@ def generate_models(components: Components, pydantic_version: PydanticVersion =
323350
324351 continue # pragma: no cover
325352
353+ # Enumerate properties for this model
326354 properties = []
327- property_iterator = (
328- schema_or_reference .properties .items ()
329- if schema_or_reference .properties is not None
330- else {}
331- )
332- for prop_name , property in property_iterator :
333- if isinstance (property , Reference ):
334- conv_property = _generate_property_from_reference (
335- name , prop_name , property , schema_or_reference
336- )
337- else :
338- conv_property = _generate_property_from_schema (
339- name , prop_name , property , schema_or_reference
340- )
355+ for conv_property in _collect_properties_from_schema (name , schema_or_reference ):
341356 properties .append (conv_property )
342357
358+ # Enumerate union types that compose this model (if any) from allOf, oneOf, anyOf
359+ parent_components = []
360+ components_iterator = (
361+ (schema_or_reference .allOf or []) + (schema_or_reference .oneOf or []) + (schema_or_reference .anyOf or [])
362+ )
363+ for parent_component in components_iterator :
364+ # For references, instead of importing properties, record inherited components
365+ if isinstance (parent_component , Reference ):
366+ ref = parent_component .ref
367+ parent_name = common .normalize_symbol (ref .split ("/" )[- 1 ])
368+ parent_components .append (ParentModel (
369+ ref = ref ,
370+ name = parent_name ,
371+ import_type = f"from .{ parent_name } import { parent_name } "
372+ ))
373+
374+ # Collect inline properties
375+ if isinstance (parent_component , Schema ):
376+ for conv_property in _collect_properties_from_schema (name , parent_component ):
377+ properties .append (conv_property )
378+
343379 template_name = MODELS_TEMPLATE_PYDANTIC_V2 if pydantic_version == PydanticVersion .V2 else MODELS_TEMPLATE
344380
345381 generated_content = jinja_env .get_template (template_name ).render (
346- schema_name = name , schema = schema_or_reference , properties = properties
382+ schema_name = name ,
383+ schema = schema_or_reference ,
384+ properties = properties ,
385+ parent_components = parent_components
347386 )
348387
349388 try :
@@ -357,6 +396,7 @@ def generate_models(components: Components, pydantic_version: PydanticVersion =
357396 content = generated_content ,
358397 openapi_object = schema_or_reference ,
359398 properties = properties ,
399+ parent_components = parent_components
360400 )
361401 )
362402
0 commit comments