1212from pydantic_core import PydanticCustomError
1313# from rune.runtime.object_registry import get_object
1414
15+ DEFAULT_META = '_ALLOWED_METADATA'
1516META_CONTAINER = '__rune_metadata'
1617REFS_CONTAINER = '__rune_references'
1718PARENT_PROP = '__rune_parent'
@@ -120,7 +121,7 @@ def get_reference(self, parent):
120121
121122class BaseMetaDataMixin :
122123 '''Base class for the meta data support of basic amd complex types'''
123- _DEFAULT_SCOPE_TYPE = 'cdm.event.common.TradeState.TradeState '
124+ _DEFAULT_SCOPE_TYPE = 'cdm.event.common.TradeState'
124125 __meta_check_disabled = False
125126
126127 @classmethod
@@ -138,29 +139,13 @@ def meta_checks_enabled(cls):
138139 '''is metadata checked during deserialize'''
139140 return not BaseMetaDataMixin .__meta_check_disabled
140141
141- def _get_meta_container (self ) -> dict [str , Any ]:
142- return self .__dict__ .get (META_CONTAINER , {})
143-
144- def _check_props_allowed (self , props : dict [str , Any ]):
145- if not props :
146- return
147- allowed = set (self ._get_meta_container ().keys ())
148- prop_keys = set (props .keys ())
149- if not prop_keys .issubset (allowed ):
150- raise ValueError ('Not allowed metadata provided: '
151- f'{ prop_keys - allowed } ' )
152-
153- def init_meta (self , allowed_meta : set [str ]):
154- ''' if not initialised, just creates empty meta slots. If the metadata
155- container is not empty, it will check if the already present keys
156- are conform to the allowed keys.
157- '''
158- meta = self .__dict__ .setdefault (META_CONTAINER , {})
159- current_meta = set (meta .keys ())
160- if not current_meta .issubset (allowed_meta ):
161- raise ValueError (f'Allowed meta { allowed_meta } differs from the '
162- f'currently existing meta slots: { current_meta } ' )
163- meta |= {k : None for k in allowed_meta - current_meta }
142+ def is_scope_instance (self ):
143+ '''is this object a scope for `scoped` keys/references'''
144+ if not (scope := self ._get_rune_scope_type ()):
145+ scope = self ._DEFAULT_SCOPE_TYPE
146+ if not (fqcn := getattr (self , '_FQRTN' , None )):
147+ fqcn = f'{ self .__class__ .__module__ } .{ self .__class__ .__qualname__ } '
148+ return fqcn == scope
164149
165150 def set_meta (self , check_allowed = True , ** kwds ):
166151 '''set some/all metadata properties'''
@@ -211,7 +196,40 @@ def get_object_by_key(self, key: str, key_type: KeyType):
211196 '''retrieve an object with a key an key type'''
212197 return self ._get_object_map (key_type )[key ]
213198
214- def bind_property_to (self , property_nm : str , ref : Reference ):
199+ def get_rune_parent (self ) -> Self | None :
200+ '''the parent object'''
201+ return self .__dict__ .get (PARENT_PROP )
202+
203+ def _get_meta_container (self ) -> dict [str , Any ]:
204+ return self .__dict__ .get (META_CONTAINER , {})
205+
206+ def _merged_allowed_meta (self , allowed_meta : set [str ]) -> set [str ]:
207+ default_meta = getattr (self , DEFAULT_META , set ())
208+ return set (allowed_meta ) | default_meta
209+
210+ def _check_props_allowed (self , props : dict [str , Any ]):
211+ if not props :
212+ return
213+ allowed = self ._merged_allowed_meta (self ._get_meta_container ().keys ())
214+ prop_keys = set (props .keys ())
215+ if not prop_keys .issubset (allowed ):
216+ raise ValueError ('Not allowed metadata provided: '
217+ f'{ prop_keys - allowed } ' )
218+
219+ def _init_meta (self , allowed_meta : set [str ]):
220+ ''' if not initialised, just creates empty meta slots. If the metadata
221+ container is not empty, it will check if the already present keys
222+ are conform to the allowed keys.
223+ '''
224+ allowed_meta = self ._merged_allowed_meta (allowed_meta )
225+ meta = self .__dict__ .setdefault (META_CONTAINER , {})
226+ current_meta = set (meta .keys ())
227+ if not current_meta .issubset (allowed_meta ):
228+ raise ValueError (f'Allowed meta { allowed_meta } differs from the '
229+ f'currently existing meta slots: { current_meta } ' )
230+ meta |= {k : None for k in allowed_meta - current_meta }
231+
232+ def _bind_property_to (self , property_nm : str , ref : Reference ):
215233 '''set the property to reference the object referenced by the key'''
216234 allowed_ref_types = getattr (self , '_KEY_REF_CONSTRAINTS' , {})
217235 if ref .key_type .rune_ref_tag not in allowed_ref_types .get (
@@ -257,23 +275,7 @@ def _get_object_map(self, key_type: KeyType) -> dict[str, Any]:
257275 # pylint: disable=protected-access
258276 return self .get_rune_parent ()._get_object_map (key_type ) # type:ignore
259277
260- @classmethod
261- def _create_unresolved_ref (cls , metadata ) -> UnresolvedReference | None :
262- if ref := {k : v for k , v in metadata .items () if k .startswith ('@ref' )}:
263- if len (ref ) != 1 :
264- ref .pop (KeyType .INTERNAL .rune_ref_tag , None )
265- if len (ref ) != 1 :
266- ref .pop (KeyType .EXTERNAL .rune_ref_tag , None )
267- if len (ref ) != 1 :
268- raise ValueError (f'Multiple references found: { ref } !' )
269- return UnresolvedReference (ref )
270- return None
271-
272- def get_rune_parent (self ) -> Self | None :
273- '''the parent object'''
274- return self .__dict__ .get (PARENT_PROP )
275-
276- def set_rune_parent (self , parent : Self ):
278+ def _set_rune_parent (self , parent : Self ):
277279 '''sets the parent object'''
278280 self .__dict__ [PARENT_PROP ] = parent
279281 if obj_maps := self .__dict__ .pop (RUNE_OBJ_MAPS , None ):
@@ -305,14 +307,26 @@ def _update_object_maps(self, new_maps):
305307 f'Duplicated keys { dup_keys } ' )
306308 local_map |= new_map
307309
308- def get_rune_refs_container (self ):
310+ def _get_rune_refs_container (self ):
309311 '''return the dictionary of the refs held'''
310312 return self .__dict__ .get (REFS_CONTAINER , {})
311313
312- def remove_rune_ref (self , name ):
314+ def _remove_rune_ref (self , name ):
313315 '''remove a reference'''
314316 return self .__dict__ [REFS_CONTAINER ].pop (name )
315317
318+ @classmethod
319+ def _create_unresolved_ref (cls , metadata ) -> UnresolvedReference | None :
320+ if ref := {k : v for k , v in metadata .items () if k .startswith ('@ref' )}:
321+ if len (ref ) != 1 :
322+ ref .pop (KeyType .INTERNAL .rune_ref_tag , None )
323+ if len (ref ) != 1 :
324+ ref .pop (KeyType .EXTERNAL .rune_ref_tag , None )
325+ if len (ref ) != 1 :
326+ raise ValueError (f'Multiple references found: { ref } !' )
327+ return UnresolvedReference (ref )
328+ return None
329+
316330 @classmethod
317331 @lru_cache
318332 def _get_rune_scope_type (cls ):
@@ -322,18 +336,11 @@ def _get_rune_scope_type(cls):
322336 try :
323337 module = importlib .import_module (
324338 cls .__module__ .split ('.' , maxsplit = 1 )[0 ])
325- return getattr (module , 'rune_scope_type' , default = None )
339+ return getattr (module , 'rune_scope_type' , None )
326340 # pylint: disable=bare-except
327341 except : # noqa
328342 return None
329343
330- def is_scope_instance (self ):
331- '''is this object a scope for `scoped` keys/references'''
332- if not (scope := self ._get_rune_scope_type ()):
333- scope = self ._DEFAULT_SCOPE_TYPE
334- fqcn = f'{ self .__class__ .__module__ } .{ self .__class__ .__qualname__ } '
335- return fqcn == scope
336-
337344
338345class ComplexTypeMetaDataMixin (BaseMetaDataMixin ):
339346 '''metadata support for complex types'''
@@ -360,7 +367,7 @@ def deserialize(cls, obj, allowed_meta: set[str]):
360367 '''method used as pydantic `validator`'''
361368 if isinstance (obj , cls ):
362369 if cls .meta_checks_enabled ():
363- obj .init_meta (allowed_meta )
370+ obj ._init_meta (allowed_meta ) # pylint: disable=protected-access
364371 return obj
365372
366373 if isinstance (obj , Reference ):
@@ -387,7 +394,7 @@ def deserialize(cls, obj, allowed_meta: set[str]):
387394 model = rune_cls .model_validate (obj ) # type: ignore
388395 model .__dict__ [META_CONTAINER ] = metadata
389396 if cls .meta_checks_enabled ():
390- model .init_meta (allowed_meta )
397+ model ._init_meta (allowed_meta ) # pylint: disable=protected-access
391398
392399 # Keys deserialization treatment
393400 model ._register_keys (metadata ) # pylint: disable=protected-access
@@ -441,7 +448,7 @@ def deserialize(cls, obj, handler, base_types, allowed_meta: set[str]):
441448 model = cls (data , ** obj ) # type: ignore
442449 model ._register_keys (obj )
443450 if cls .meta_checks_enabled ():
444- model .init_meta (allowed_meta )
451+ model ._init_meta (allowed_meta ) # pylint: disable=protected-access
445452 return handler (model )
446453
447454 @classmethod
@@ -553,23 +560,6 @@ def __new__(cls, value, **kwds):
553560 obj .set_meta (check_allowed = False , ** kwds )
554561 return obj
555562
556- # @classmethod
557- # @lru_cache
558- # def serializer(cls):
559- # '''should return the validator for the specific class'''
560- # ser_fn = partial(cls.serialise, base_type=Decimal)
561- # return PlainSerializer(ser_fn, return_type=dict)
562-
563- # @classmethod
564- # @lru_cache
565- # def validator(cls, allowed_meta: tuple[str]):
566- # '''default validator for the specific class'''
567- # allowed = set(allowed_meta)
568- # return WrapValidator(partial(cls.deserialize,
569- # base_types=(Decimal, float, int, str),
570- # allowed_meta=allowed),
571- # json_schema_input_type=float | int | str | dict)
572-
573563
574564class _EnumWrapperDefaultVal (Enum ):
575565 '''marker for not set value in enum wrapper'''
@@ -641,7 +631,7 @@ def deserialize(cls, obj, allowed_meta: set[str]):
641631 model .set_meta (check_allowed = False , ** obj )
642632 model ._register_keys (obj ) # pylint: disable=protected-access
643633 if _EnumWrapper .meta_checks_enabled ():
644- model .init_meta (allowed_meta )
634+ model ._init_meta (allowed_meta ) # pylint: disable=protected-access
645635 return model
646636
647637 @classmethod
0 commit comments