11from __future__ import annotations
22
3- from dataclasses import dataclass
43from itertools import chain
5- from typing import Any , ClassVar , Iterable , NamedTuple
4+ from typing import Any , ClassVar , Iterable
65
7- from attrs import define , evolve
6+ from attrs import define , evolve , field
87
98from ... import Config , utils
109from ... import schema as oai
1514from .schemas import Class , ReferencePath , Schemas , parse_reference_path
1615
1716
18- @dataclass
17+ @define
1918class ModelDetails :
19+ """Container for basic attributes of a model schema that can be computed separately"""
20+
2021 required_properties : list [Property ] | None = None
2122 optional_properties : list [Property ] | None = None
2223 additional_properties : Property | None = None
23- relative_imports : set [str ] | None = None
24- lazy_imports : set [str ] | None = None
24+ relative_imports : set [str ] = field ( factory = set )
25+ lazy_imports : set [str ] = field ( factory = set )
2526
2627
2728@define
@@ -88,11 +89,7 @@ def build(
8889 )
8990 if isinstance (data_or_err , PropertyError ):
9091 return data_or_err , schemas
91- property_data , details .additional_properties = data_or_err
92- details .required_properties = property_data .required_props
93- details .optional_properties = property_data .optional_props
94- details .relative_imports = property_data .relative_imports
95- details .lazy_imports = property_data .lazy_imports
92+ details = data_or_err
9693 for root in roots :
9794 if isinstance (root , utils .ClassName ):
9895 continue
@@ -142,11 +139,11 @@ def additional_properties(self) -> Property | None:
142139
143140 @property
144141 def relative_imports (self ) -> set [str ]:
145- return self .details .relative_imports or set ()
142+ return self .details .relative_imports
146143
147144 @property
148145 def lazy_imports (self ) -> set [str ] | None :
149- return self .details .lazy_imports or set ()
146+ return self .details .lazy_imports
150147
151148 @classmethod
152149 def convert_value (cls , value : Any ) -> Value | None | PropertyError :
@@ -253,22 +250,14 @@ def _resolve_naming_conflict(first: Property, second: Property, config: Config)
253250 return None
254251
255252
256- class _PropertyData (NamedTuple ):
257- optional_props : list [Property ]
258- required_props : list [Property ]
259- relative_imports : set [str ]
260- lazy_imports : set [str ]
261- schemas : Schemas
262-
263-
264253def _process_properties ( # noqa: PLR0911
265254 * ,
266255 data : oai .Schema ,
267256 schemas : Schemas ,
268257 class_name : utils .ClassName ,
269258 config : Config ,
270259 roots : set [ReferencePath | utils .ClassName ],
271- ) -> _PropertyData | PropertyError :
260+ ) -> tuple [ ModelDetails | PropertyError , Schemas ] :
272261 from . import property_from_data
273262 from .merge_properties import merge_properties
274263
@@ -303,19 +292,19 @@ def _add_if_no_conflict(new_prop: Property) -> PropertyError | None:
303292 if isinstance (sub_prop , oai .Reference ):
304293 ref_path = parse_reference_path (sub_prop .ref )
305294 if isinstance (ref_path , ParseError ):
306- return PropertyError (detail = ref_path .detail , data = sub_prop )
295+ return PropertyError (detail = ref_path .detail , data = sub_prop ), schemas
307296 sub_model = schemas .classes_by_reference .get (ref_path )
308297 if sub_model is None :
309- return PropertyError (f"Reference { sub_prop .ref } not found" )
298+ return PropertyError (f"Reference { sub_prop .ref } not found" ), schemas
310299 if not isinstance (sub_model , ModelProperty ):
311- return PropertyError ("Cannot take allOf a non-object" )
300+ return PropertyError ("Cannot take allOf a non-object" ), schemas
312301 # Properties of allOf references first should be processed first
313302 if sub_model .needs_post_processing ():
314- return PropertyError (f"Reference { sub_model .name } in allOf was not processed" , data = sub_prop )
303+ return PropertyError (f"Reference { sub_model .name } in allOf was not processed" , data = sub_prop ), schemas
315304 for prop in chain (sub_model .required_properties , sub_model .optional_properties ):
316305 err = _add_if_no_conflict (prop )
317306 if err is not None :
318- return err
307+ return err , schemas
319308 schemas .add_dependencies (ref_path = ref_path , roots = roots )
320309 else :
321310 unprocessed_props .extend (sub_prop .properties .items () if sub_prop .properties else [])
@@ -336,12 +325,12 @@ def _add_if_no_conflict(new_prop: Property) -> PropertyError | None:
336325 if not isinstance (prop_or_error , PropertyError ):
337326 prop_or_error = _add_if_no_conflict (prop_or_error )
338327 if isinstance (prop_or_error , PropertyError ):
339- return prop_or_error
328+ return prop_or_error , schemas
340329
341- return _gather_property_data (properties .values (), schemas )
330+ return _gather_property_data (properties .values ()) , schemas
342331
343332
344- def _gather_property_data (properties : Iterable [Property ], schemas : Schemas ) -> _PropertyData :
333+ def _gather_property_data (properties : Iterable [Property ]) -> ModelDetails :
345334 required_properties : list [Property ] = []
346335 optional_properties : list [Property ] = []
347336 relative_imports : set [str ] = set ()
@@ -350,12 +339,12 @@ def _gather_property_data(properties: Iterable[Property], schemas: Schemas) -> _
350339 (required_properties if prop .required else optional_properties ).append (prop )
351340 lazy_imports .update (prop .get_lazy_imports (prefix = ".." ))
352341 relative_imports .update (prop .get_imports (prefix = ".." ))
353- return _PropertyData (
354- optional_props = optional_properties ,
355- required_props = required_properties ,
342+ return ModelDetails (
343+ optional_properties = optional_properties ,
344+ required_properties = required_properties ,
356345 relative_imports = relative_imports ,
357346 lazy_imports = lazy_imports ,
358- schemas = schemas ,
347+ additional_properties = None ,
359348 )
360349
361350
@@ -410,13 +399,12 @@ def _process_property_data(
410399 class_info : Class ,
411400 config : Config ,
412401 roots : set [ReferencePath | utils .ClassName ],
413- ) -> tuple [tuple [ _PropertyData , Property | None ] | PropertyError , Schemas ]:
414- property_data = _process_properties (
402+ ) -> tuple [ModelDetails | PropertyError , Schemas ]:
403+ model_details , schemas = _process_properties (
415404 data = data , schemas = schemas , class_name = class_info .name , config = config , roots = roots
416405 )
417- if isinstance (property_data , PropertyError ):
418- return property_data , schemas
419- schemas = property_data .schemas
406+ if isinstance (model_details , PropertyError ):
407+ return model_details , schemas
420408
421409 additional_properties , schemas = _get_additional_properties (
422410 schema_additional = data .additionalProperties ,
@@ -430,10 +418,11 @@ def _process_property_data(
430418 elif additional_properties is None :
431419 pass
432420 else :
433- property_data .relative_imports .update (additional_properties .get_imports (prefix = ".." ))
434- property_data .lazy_imports .update (additional_properties .get_lazy_imports (prefix = ".." ))
421+ model_details = evolve (model_details , additional_properties = additional_properties )
422+ model_details .relative_imports .update (additional_properties .get_imports (prefix = ".." ))
423+ model_details .lazy_imports .update (additional_properties .get_lazy_imports (prefix = ".." ))
435424
436- return ( property_data , additional_properties ) , schemas
425+ return model_details , schemas
437426
438427
439428def process_model (model_prop : ModelProperty , * , schemas : Schemas , config : Config ) -> Schemas | PropertyError :
@@ -455,12 +444,8 @@ def process_model(model_prop: ModelProperty, *, schemas: Schemas, config: Config
455444 if isinstance (data_or_err , PropertyError ):
456445 return data_or_err
457446
458- property_data , additional_properties = data_or_err
459-
460- model_prop .details .required_properties = property_data .required_props
461- model_prop .details .optional_properties = property_data .optional_props
462- model_prop .details .additional_properties = additional_properties
463- model_prop .set_relative_imports (property_data .relative_imports )
464- model_prop .set_lazy_imports (property_data .lazy_imports )
447+ model_prop .details = data_or_err
448+ model_prop .set_relative_imports (data_or_err .relative_imports )
449+ model_prop .set_lazy_imports (data_or_err .lazy_imports )
465450
466451 return schemas
0 commit comments