@@ -30,12 +30,13 @@ class ModelList(UserList[Any]):
3030 """A list that automatically converts dictionaries to BaseModel objects."""
3131
3232 def __init__ (
33- self , iterable : Iterable [Any ] | None = None , model_class : type ["BaseModel" ] | None = None
33+ self ,
34+ iterable : Iterable [Any ] | None = None ,
35+ model_class : type ["BaseModel" ] | None = None , # noqa: WPS221
3436 ) -> None :
3537 self ._model_class = model_class or BaseModel
36- super ().__init__ (
37- self ._process_item (item ) for item in iterable
38- ) if iterable is not None else super ().__init__ ()
38+ iterable = iterable or []
39+ super ().__init__ ([self ._process_item (item ) for item in iterable ])
3940
4041 @override
4142 def append (self , item : Any ) -> None :
@@ -65,7 +66,7 @@ def _process_item(self, item: Any) -> Any:
6566class BaseModel :
6667 """Base dataclass for models providing object-only access and case conversion."""
6768
68- def __init__ (self , ** kwargs : Any ) -> None :
69+ def __init__ (self , ** kwargs : Any ) -> None : # noqa: WPS210
6970 """Processes resource data to convert keys and handle nested structures."""
7071 # Get type hints for field mapping
7172 hints = getattr (self , "__annotations__" , {})
@@ -78,49 +79,19 @@ def __init__(self, **kwargs: Any) -> None:
7879 processed_value = self ._process_value (value , target_class = target_class )
7980 object .__setattr__ (self , mapped_key , processed_value )
8081
81- def _process_value (self , value : Any , target_class : Any = None ) -> Any : # noqa: C901
82- """Recursively processes values to ensure nested dicts are BaseModels."""
83- if isinstance (value , dict ) and not isinstance (value , BaseModel ):
84- # If a target class is provided and it's a subclass of BaseModel, use it
85- if (
86- target_class
87- and isinstance (target_class , type )
88- and issubclass (target_class , BaseModel )
89- ):
90- return target_class (** value )
91- return BaseModel (** value )
92-
93- if isinstance (value , (list , UserList )) and not isinstance (value , ModelList ):
94- # Try to determine the model class for the list elements from type hints
95- model_class = BaseModel
96- if target_class :
97- # Handle list[ModelClass]
98-
99- origin = get_origin (target_class )
100- if origin is list :
101- args = get_args (target_class )
102- if args and isinstance (args [0 ], type ) and issubclass (args [0 ], BaseModel ):
103- model_class = args [0 ]
104-
105- return ModelList (value , model_class = model_class )
106- # Recursively handle BaseModel if it's already one
107- if isinstance (value , BaseModel ):
108- return value
109- return value
110-
11182 def __getattr__ (self , name : str ) -> Any :
11283 # 1. Try to find the attribute in __dict__ (includes attributes set in __init__)
11384 if name in self .__dict__ :
114- return self .__dict__ [name ]
85+ return self .__dict__ [name ] # noqa: WPS420 WPS529
11586
11687 # 2. Check for methods or properties
11788 try :
11889 return object .__getattribute__ (self , name )
11990 except AttributeError :
120- pass
91+ pass # noqa: WPS420
12192
12293 raise AttributeError (
123- f"'{ self .__class__ .__name__ } ' object has no attribute '{ name } '" ,
94+ f"'{ self .__class__ .__name__ } ' object has no attribute '{ name } '" , # noqa: WPS237
12495 )
12596
12697 @override
@@ -162,6 +133,36 @@ def _serialize_value(self, value: Any) -> Any:
162133 return [self ._serialize_value (item ) for item in value ]
163134 return value
164135
136+ def _process_value (self , value : Any , target_class : Any = None ) -> Any : # noqa: WPS231 C901
137+ """Recursively processes values to ensure nested dicts are BaseModels."""
138+ if isinstance (value , dict ) and not isinstance (value , BaseModel ):
139+ # If a target class is provided and it's a subclass of BaseModel, use it
140+ if (
141+ target_class
142+ and isinstance (target_class , type )
143+ and issubclass (target_class , BaseModel )
144+ ):
145+ return target_class (** value )
146+ return BaseModel (** value )
147+
148+ if isinstance (value , (list , UserList )) and not isinstance (value , ModelList ):
149+ # Try to determine the model class for the list elements from type hints
150+ model_class = BaseModel
151+ if target_class :
152+ # Handle list[ModelClass]
153+
154+ origin = get_origin (target_class )
155+ if origin is list :
156+ args = get_args (target_class )
157+ if args and isinstance (args [0 ], type ) and issubclass (args [0 ], BaseModel ): # noqa: WPS221
158+ model_class = args [0 ] # noqa: WPS220
159+
160+ return ModelList (value , model_class = model_class )
161+ # Recursively handle BaseModel if it's already one
162+ if isinstance (value , BaseModel ):
163+ return value
164+ return value
165+
165166
166167class Model (BaseModel ):
167168 """Provides a resource to interact with api data using fluent interfaces."""
0 commit comments