3232__PRIMITIVE_TYPES = {int , float , complex , str , bytes , bytearray , bool }
3333
3434
35- def is_sequence (obj : Any ) -> bool :
35+ def _is_sequence (obj : Any ) -> bool :
3636 """Check if object implements `__iter__` method"""
3737 return hasattr (obj , "__iter__" )
3838
3939
40- def is_subscriptable (obj : Any ) -> bool :
40+ def _is_subscriptable (obj : Any ) -> bool :
4141 """Check if object implements `__get_item__` method"""
4242 return hasattr (obj , "__get_item__" )
4343
4444
45- def is_primitive (obj : Any ) -> bool :
45+ def _is_primitive (obj : Any ) -> bool :
4646 """Check if object type is primitive"""
4747 return type (obj ) in __PRIMITIVE_TYPES
4848
@@ -67,12 +67,26 @@ def map(
6767 fields_mapping : FieldsMap = None ,
6868 deepcopy : bool = True ,
6969 ) -> T :
70- """Produces output object mapped from source object and custom arguments
70+ """Produces output object mapped from source object and custom arguments.
7171
7272 Parameters:
7373 skip_none_values - do not map fields that has None value
7474 fields_mapping - mapping for fields with different names
7575 deepcopy - should we deepcopy all attributes? [default: True]
76+
77+ Args:
78+ obj (S): _description_
79+ skip_none_values (bool, optional): Skip None values when creating `target class` obj. Defaults to False.
80+ fields_mapping (FieldsMap, optional): Custom mapping.
81+ Specify dictionary in format {"field_name": value_object}. Defaults to None.
82+ deepcopy (bool, optional): Applies deepcopy to all child objects when copy into output instance.
83+ Defaults to True.
84+
85+ Raises:
86+ CircularReferenceError: Circular references in `source class` object are not allowed yet.
87+
88+ Returns:
89+ T: instance of `target class` with mapped values from `source class` or custom `fields_mapping` dictionary.
7690 """
7791 return self .__mapper ._map_common (
7892 obj ,
@@ -97,22 +111,22 @@ def __init__(self) -> None:
97111 def add_spec (self , classifier : Type [T ], spec_func : SpecFunction [T ]) -> None :
98112 """Add a spec function for all classes in inherited from base class.
99113
100- Parameters:
101- * classifier - base class to identify all descendant classes
102- * spec_func - returns a list of fields (List[str]) for target class
103- that are accepted in constructor
114+ Args:
115+ classifier (ClassifierFunction[T]): base class to identify all descendant classes.
116+ spec_func (SpecFunction[T]): get list of fields (List[str]) for `target class` to be passed in constructor.
104117 """
105118 ...
106119
107120 @overload
108- def add_spec (self , classifier : ClassifierFunction [T ], spec_func : SpecFunction [T ]) -> None :
121+ def add_spec (
122+ self , classifier : ClassifierFunction [T ], spec_func : SpecFunction [T ]
123+ ) -> None :
109124 """Add a spec function for all classes identified by classifier function.
110125
111- Parameters:
112- * classifier - boolean predicate that identifies a group of classes
113- by certain characteristics: if class has a specific method or a field, etc.
114- * spec_func - returns a list of fields (List[str]) for target class
115- that are accepted in constructor
126+ Args:
127+ classifier (ClassifierFunction[T]): boolean predicate that identifies a group of classes
128+ by certain characteristics: if class has a specific method or a field, etc.
129+ spec_func (SpecFunction[T]): get list of fields (List[str]) for `target class` to be passed in constructor.
116130 """
117131 ...
118132
@@ -146,16 +160,21 @@ def add(
146160 ) -> None :
147161 """Adds mapping between object of `source class` to an object of `target class`.
148162
149- Parameters
150- ----------
151- source_cls : Type
152- Source class to map from
153- target_cls : Type
154- Target class to map to
155- override : bool, optional
156- Override existing `source class` mapping to use new `target class`
157- deepcopy : bool, optional
158- Should we deepcopy all attributes? [default: True]
163+ Args:
164+ source_cls (Type[S]): Source class to map from
165+ target_cls (Type[T]): Target class to map to
166+ override (bool, optional): Override existing `source class` mapping to use new `target class`.
167+ Defaults to False.
168+ fields_mapping (FieldsMap, optional): Custom mapping.
169+ Specify dictionary in format {"field_name": value_object}. Defaults to None.
170+ deepcopy (bool, optional): Applies deepcopy to all child objects when copy into output instance.
171+ Defaults to True.
172+
173+ Raises:
174+ DuplicatedRegistrationError: Same mapping for `source class` was added.
175+ Only one mapping per source class can exist at a time for now.
176+ You can specify target class manually using `mapper.to(target_cls)` method
177+ or use `override` argument to replace existing mapping.
159178 """
160179 if source_cls in self ._mappings and not override :
161180 raise DuplicatedRegistrationError (
@@ -169,22 +188,42 @@ def map(
169188 * ,
170189 skip_none_values : bool = False ,
171190 fields_mapping : FieldsMap = None ,
172- deepcopy : bool = None ,
191+ deepcopy : bool = True ,
173192 ) -> T : # type: ignore [type-var]
174- """Produces output object mapped from source object and custom arguments"""
193+ """Produces output object mapped from source object and custom arguments
194+
195+ Args:
196+ obj (object): Source object to map to `target class`.
197+ skip_none_values (bool, optional): Skip None values when creating `target class` obj. Defaults to False.
198+ fields_mapping (FieldsMap, optional): Custom mapping.
199+ Specify dictionary in format {"field_name": value_object}. Defaults to None.
200+ deepcopy (bool, optional): Applies deepcopy to all child objects when copy into output instance.
201+ Defaults to True.
202+
203+ Raises:
204+ MappingError: No `target class` specified to be mapped into.
205+ Register mappings using `mapped.add(...)` or specify `target class` using `mapper.to(target_cls).map()`.
206+ CircularReferenceError: Circular references in `source class` object are not allowed yet.
207+
208+ Returns:
209+ T: instance of `target class` with mapped values from `source class` or custom `fields_mapping` dictionary.
210+ """
175211 obj_type = type (obj )
176212 if obj_type not in self ._mappings :
177213 raise MappingError (f"Missing mapping type for input type { obj_type } " )
178214 obj_type_preffix = f"{ obj_type .__name__ } ."
179215
180- target_cls , target_cls_field_mappings , target_deepcopy = self ._mappings [obj_type ]
216+ target_cls , target_cls_field_mappings , target_deepcopy = self ._mappings [
217+ obj_type
218+ ]
181219
182220 common_fields_mapping = fields_mapping
183221 if target_cls_field_mappings :
184222 # transform mapping if it's from source class field
185223 common_fields_mapping = {
186224 target_obj_field : getattr (obj , source_field [len (obj_type_preffix ) :])
187- if isinstance (source_field , str ) and source_field .startswith (obj_type_preffix )
225+ if isinstance (source_field , str )
226+ and source_field .startswith (obj_type_preffix )
188227 else source_field
189228 for target_obj_field , source_field in target_cls_field_mappings .items ()
190229 }
@@ -217,13 +256,15 @@ def _get_fields(self, target_cls: Type[T]) -> Iterable[str]:
217256 if classifier (target_cls ):
218257 return self ._classifier_specs [classifier ](target_cls )
219258
220- raise MappingError (f"No spec function is added for base class of { type (target_cls )} " )
259+ raise MappingError (
260+ f"No spec function is added for base class of { type (target_cls )} "
261+ )
221262
222263 def _map_subobject (
223264 self , obj : S , _visited_stack : Set [int ], skip_none_values : bool = False
224265 ) -> Any :
225266 """Maps subobjects recursively"""
226- if is_primitive (obj ):
267+ if _is_primitive (obj ):
227268 return obj
228269
229270 obj_id = id (obj )
@@ -238,10 +279,12 @@ def _map_subobject(
238279 else :
239280 _visited_stack .add (obj_id )
240281
241- if is_sequence (obj ):
282+ if _is_sequence (obj ):
242283 if isinstance (obj , dict ):
243284 result = {
244- k : self ._map_subobject (v , _visited_stack , skip_none_values = skip_none_values )
285+ k : self ._map_subobject (
286+ v , _visited_stack , skip_none_values = skip_none_values
287+ )
245288 for k , v in obj .items ()
246289 }
247290 else :
@@ -269,12 +312,23 @@ def _map_common(
269312 fields_mapping : FieldsMap = None ,
270313 deepcopy : bool = True ,
271314 ) -> T :
272- """Produces output object mapped from source object and custom arguments
273-
274- Parameters:
275- skip_none_values - do not map fields that has None value
276- fields_mapping - fields mappings for fields with different names
277- deepcopy - Should we deepcopy all attributes? [default: True]
315+ """Produces output object mapped from source object and custom arguments.
316+
317+ Args:
318+ obj (S): Source object to map to `target class`.
319+ target_cls (Type[T]): Target class to map to.
320+ _visited_stack (Set[int]): Visited child objects. To avoid infinite recursive calls.
321+ skip_none_values (bool, optional): Skip None values when creating `target class` obj. Defaults to False.
322+ fields_mapping (FieldsMap, optional): Custom mapping.
323+ Specify dictionary in format {"field_name": value_object}. Defaults to None.
324+ deepcopy (bool, optional): Applies deepcopy to all child objects when copy into output instance.
325+ Defaults to True.
326+
327+ Raises:
328+ CircularReferenceError: Circular references in `source class` object are not allowed yet.
329+
330+ Returns:
331+ T: Instance of `target class` with mapped fields.
278332 """
279333 obj_id = id (obj )
280334
@@ -285,7 +339,7 @@ def _map_common(
285339 target_cls_fields = self ._get_fields (target_cls )
286340
287341 mapped_values : Dict [str , Any ] = {}
288- is_obj_subscriptable = is_subscriptable (obj )
342+ is_obj_subscriptable = _is_subscriptable (obj )
289343 for field_name in target_cls_fields :
290344 if (
291345 (fields_mapping and field_name in fields_mapping )
@@ -316,5 +370,12 @@ def _map_common(
316370 return cast (target_cls , target_cls (** mapped_values )) # type: ignore [valid-type]
317371
318372 def to (self , target_cls : Type [T ]) -> MappingWrapper [T ]:
319- """Specify target class to map source object to"""
373+ """Specify `target class` to which map `source class` object.
374+
375+ Args:
376+ target_cls (Type[T]): Target class.
377+
378+ Returns:
379+ MappingWrapper[T]: Mapping wrapper. Use `map` method to perform mapping now.
380+ """
320381 return MappingWrapper [T ](self , target_cls )
0 commit comments