@@ -146,75 +146,104 @@ def convert_to_entity_by_key_static(
146146 except Exception as e :
147147 raise RuntimeError (f"Could not convert document { key } to entity of type { entity_class } " , e )
148148
149+ @staticmethod
150+ def _invoke_after_conversion_to_entity_event (
151+ session_hook : Optional ["InMemoryDocumentSessionOperations" ],
152+ key : str ,
153+ object_type : Optional [_T ],
154+ document_deepcopy : dict ,
155+ ):
156+ if session_hook :
157+ session_hook .after_conversion_to_entity_invoke (
158+ AfterConversionToEntityEventArgs (session_hook , key , object_type , document_deepcopy )
159+ )
160+
149161 @staticmethod
150162 def convert_to_entity_static (
151163 document : dict ,
152164 object_type : [_T ],
153165 conventions : "DocumentConventions" ,
154166 session_hook : Optional ["InMemoryDocumentSessionOperations" ] = None ,
155167 ) -> _T :
168+ # This method has two steps - extract the type (I), and then convert it into the entity (II)
169+ # todo: Separate it into two different functions and isolate the return statements from the first part
170+
171+ # I. Extract the object type
156172 metadata = document .pop ("@metadata" )
157173 document_deepcopy = deepcopy (document )
174+
175+ # 1. Get type from metadata
158176 type_from_metadata = conventions .try_get_type_from_metadata (metadata )
159- is_inherit = False
177+ is_projection = False
160178 key = metadata .get (constants .Documents .Metadata .ID , None )
179+
180+ # Fire before conversion to entity events
161181 if session_hook :
162182 session_hook .before_conversion_to_entity_invoke (
163183 BeforeConversionToEntityEventArgs (session_hook , key , object_type , document_deepcopy )
164184 )
165185
186+ # 1.1 Check if passed object type (or extracted from metadata) is a dictionary
166187 if object_type == dict or type_from_metadata == "builtins.dict" :
167- session_hook .after_conversion_to_entity_invoke (
168- AfterConversionToEntityEventArgs (session_hook , key , document_deepcopy , document_deepcopy )
169- )
188+ EntityToJson ._invoke_after_conversion_to_entity_event (session_hook , key , object_type , document_deepcopy )
170189 return document_deepcopy
171190
191+ # 1.2 If there's no object type in metadata
172192 if type_from_metadata is None :
193+ # 1.2.1 Try to set it with passed object type
173194 if object_type is not None :
174195 metadata ["Raven-Python-Type" ] = "{0}.{1}" .format (object_type .__module__ , object_type .__name__ )
175- else : # no type defined on document or during load, return a dict
196+ # 1.2.2 no type defined on document or during load, return a dict
197+ else :
176198 dyn = _DynamicStructure (** document_deepcopy )
177- if session_hook :
178- session_hook .after_conversion_to_entity_invoke (
179- AfterConversionToEntityEventArgs (session_hook , key , document_deepcopy , dyn )
180- )
199+ EntityToJson ._invoke_after_conversion_to_entity_event (session_hook , key , object_type , document_deepcopy )
181200 return dyn
201+
202+ # 2. There was a type in the metadata
182203 else :
183204 object_from_metadata = Utils .import_class (type_from_metadata )
205+ # 2.1 Import was successful
184206 if object_from_metadata is not None :
185- if object_type is None :
207+ # 2.1.1 Set object_type to successfully imported type/ from metadata inherits from passed object_type
208+ if object_type is None or Utils .is_inherit (object_type , object_from_metadata ):
186209 object_type = object_from_metadata
187210
188- elif Utils .is_inherit (object_type , object_from_metadata ):
189- object_type = object_from_metadata
190- is_inherit = True
211+ # 2.1.2 Passed type is not a type from metadata, neither there's no inheritance - probably projection
191212 elif object_type is not object_from_metadata :
192- # todo: projection
213+ is_projection = True
193214 if not all ([name in object_from_metadata .__dict__ for name in object_type .__dict__ ]):
194215 raise exceptions .InvalidOperationException (
195216 f"Cannot covert document from type { object_from_metadata } to { object_type } "
196217 )
218+
219+ # We have object type set - it was either extracted or passed through args
220+
221+ # II. Conversion to entity part
222+
223+ # By custom defined 'from_json' serializer class method
197224 # todo: make separate interface to do from_json
198225 if "from_json" in object_type .__dict__ and inspect .ismethod (object_type .from_json ):
199226 entity = object_type .from_json (document_deepcopy )
200227
201- elif is_inherit :
202- entity = Utils .convert_json_dict_to_object (document_deepcopy , object_type )
203-
204- else :
228+ # By projection
229+ elif is_projection :
205230 entity = _DynamicStructure (** document_deepcopy )
206231 entity .__class__ = object_type
207232 try :
208233 entity = Utils .initialize_object (document_deepcopy , object_type )
209234 except TypeError as e :
210235 raise InvalidOperationException ("Probably projection error" , e )
211236
237+ # Happy path - successful extraction of the type from metadata, if not - got object_type passed to arguments
238+ else :
239+ entity = Utils .convert_json_dict_to_object (document_deepcopy , object_type )
240+
241+ EntityToJson ._invoke_after_conversion_to_entity_event (session_hook , key , object_type , document_deepcopy )
242+
243+ # Try to set Id
212244 if "Id" in entity .__dict__ :
213245 entity .Id = metadata .get ("@id" , None )
214- if session_hook :
215- session_hook .after_conversion_to_entity_invoke (
216- AfterConversionToEntityEventArgs (session_hook , key , document_deepcopy , entity )
217- )
246+
218247 return entity
219248
220249 def remove_from_missing (self , entity ):
0 commit comments