33import dataclasses as dc
44import itertools
55import operator
6- from collections .abc import Callable , Iterable , Set
6+ from collections .abc import Callable , Container , Iterable , Set
77from typing import Any , Self
88
99from openapi_pydantic .v3 .v3_1 import schema as schema31
@@ -93,6 +93,22 @@ class MetaModel:
9393 all_of : list [MetaModel ] | None = None
9494
9595 def normalize_model (self ) -> MetaModel | None :
96+ # if this doesn't have any assertions and only a single sub-schema, return that sub-schema
97+ if len (self .any_of or ()) + len (self .one_of or ()) + len (self .all_of or ()) == 1 :
98+ if self .any_of :
99+ candidate = self .any_of [0 ]
100+ elif self .one_of :
101+ candidate = self .one_of [0 ]
102+ elif self .all_of :
103+ candidate = self .all_of [0 ]
104+ else :
105+ raise ValueError
106+
107+ if self ._only_constraints () == MetaModel (stack = self .stack ) or self ._only_constraints () == MetaModel (
108+ stack = self .stack , type_ = candidate .type_
109+ ):
110+ return candidate
111+
96112 if self .type_ is None :
97113 self .type_ = _all_types ()
98114
@@ -117,7 +133,7 @@ def normalize_model(self) -> MetaModel | None:
117133 if nsub is None :
118134 # ignore bottom types
119135 continue
120- if dc . replace ( sub , description = None ) == dc . replace ( nsub , stack = sub . stack , description = None ):
136+ if sub . _comparable ( ) == nsub . _comparable ( ):
121137 # no change
122138 nsub = sub
123139 items .append (nsub )
@@ -376,7 +392,7 @@ def _as_object_anno(self, root_package: str) -> python.AnnotatedType:
376392 else :
377393 return resolve_type_name (root_package , self .stack )
378394
379- def _has_annotations (self ) -> bool :
395+ def _has_annotations (self , excluding : Container [ str ] = () ) -> bool :
380396 return (
381397 any (
382398 getattr (self , key ) is not None
@@ -396,13 +412,18 @@ def _has_annotations(self) -> bool:
396412 'one_of' ,
397413 'all_of' ,
398414 )
415+ if key not in excluding
399416 )
400417 or self .additional_props is not True
401418 or bool (self .properties )
402419 or bool (self .props_required )
403420 or self .type_ != _all_types ()
404421 )
405422
423+ def _comparable (self ) -> Self :
424+ """Return a copy without anotations, useful for comparing."""
425+ return dc .replace (self , description = None , title = None , stack = Stack ())
426+
406427
407428def _as_class_field (anno : python .AnnotatedType , name : str , required : bool ) -> python .AnnotatedVariable :
408429 python_name = names .maybe_mangle_name (name )
0 commit comments