@@ -146,75 +146,104 @@ def convert_to_entity_by_key_static(
146
146
except Exception as e :
147
147
raise RuntimeError (f"Could not convert document { key } to entity of type { entity_class } " , e )
148
148
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
+
149
161
@staticmethod
150
162
def convert_to_entity_static (
151
163
document : dict ,
152
164
object_type : [_T ],
153
165
conventions : "DocumentConventions" ,
154
166
session_hook : Optional ["InMemoryDocumentSessionOperations" ] = None ,
155
167
) -> _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
156
172
metadata = document .pop ("@metadata" )
157
173
document_deepcopy = deepcopy (document )
174
+
175
+ # 1. Get type from metadata
158
176
type_from_metadata = conventions .try_get_type_from_metadata (metadata )
159
- is_inherit = False
177
+ is_projection = False
160
178
key = metadata .get (constants .Documents .Metadata .ID , None )
179
+
180
+ # Fire before conversion to entity events
161
181
if session_hook :
162
182
session_hook .before_conversion_to_entity_invoke (
163
183
BeforeConversionToEntityEventArgs (session_hook , key , object_type , document_deepcopy )
164
184
)
165
185
186
+ # 1.1 Check if passed object type (or extracted from metadata) is a dictionary
166
187
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 )
170
189
return document_deepcopy
171
190
191
+ # 1.2 If there's no object type in metadata
172
192
if type_from_metadata is None :
193
+ # 1.2.1 Try to set it with passed object type
173
194
if object_type is not None :
174
195
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 :
176
198
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 )
181
200
return dyn
201
+
202
+ # 2. There was a type in the metadata
182
203
else :
183
204
object_from_metadata = Utils .import_class (type_from_metadata )
205
+ # 2.1 Import was successful
184
206
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 ):
186
209
object_type = object_from_metadata
187
210
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
191
212
elif object_type is not object_from_metadata :
192
- # todo: projection
213
+ is_projection = True
193
214
if not all ([name in object_from_metadata .__dict__ for name in object_type .__dict__ ]):
194
215
raise exceptions .InvalidOperationException (
195
216
f"Cannot covert document from type { object_from_metadata } to { object_type } "
196
217
)
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
197
224
# todo: make separate interface to do from_json
198
225
if "from_json" in object_type .__dict__ and inspect .ismethod (object_type .from_json ):
199
226
entity = object_type .from_json (document_deepcopy )
200
227
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 :
205
230
entity = _DynamicStructure (** document_deepcopy )
206
231
entity .__class__ = object_type
207
232
try :
208
233
entity = Utils .initialize_object (document_deepcopy , object_type )
209
234
except TypeError as e :
210
235
raise InvalidOperationException ("Probably projection error" , e )
211
236
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
212
244
if "Id" in entity .__dict__ :
213
245
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
+
218
247
return entity
219
248
220
249
def remove_from_missing (self , entity ):
0 commit comments