Skip to content

Commit 3453547

Browse files
Merge pull request #7 from Cloudrisk/develop
minor fix to check in addition to _KEY_REF_CONSTRAINTS the type speci…
2 parents 067d045 + c956729 commit 3453547

File tree

1 file changed

+14
-9
lines changed

1 file changed

+14
-9
lines changed

src/rune/runtime/metadata.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from enum import Enum
66
from functools import partial, lru_cache
77
from decimal import Decimal
8-
from typing import Any, Never, get_args
8+
from typing import Any, Never, get_args, Iterable
99
from typing_extensions import Self, Tuple
1010
from pydantic import (PlainSerializer, PlainValidator, WrapValidator,
1111
WrapSerializer)
@@ -19,6 +19,10 @@
1919
RUNE_OBJ_MAPS = '__rune_object_maps'
2020

2121

22+
def _replaceable(prop):
23+
return isinstance(prop, (BaseMetaDataMixin, UnresolvedReference, Reference))
24+
25+
2226
def _py_to_ser_key(key: str) -> str:
2327
if key[0] == '@':
2428
return key
@@ -203,8 +207,9 @@ def get_rune_parent(self) -> Self | None:
203207
def _get_meta_container(self) -> dict[str, Any]:
204208
return self.__dict__.get(META_CONTAINER, {})
205209

206-
def _merged_allowed_meta(self, allowed_meta: set[str]) -> set[str]:
207-
default_meta = getattr(self, DEFAULT_META, set())
210+
def _merged_allowed_meta(
211+
self, allowed_meta: set[str] | Iterable[str]) -> set[str]:
212+
default_meta: set[str] = getattr(self, DEFAULT_META, set())
208213
return set(allowed_meta) | default_meta
209214

210215
def _check_props_allowed(self, props: dict[str, Any]):
@@ -231,9 +236,10 @@ def _init_meta(self, allowed_meta: set[str]):
231236

232237
def _bind_property_to(self, property_nm: str, ref: Reference):
233238
'''set the property to reference the object referenced by the key'''
239+
old_val = getattr(self, property_nm)
234240
allowed_ref_types = getattr(self, '_KEY_REF_CONSTRAINTS', {})
235-
if ref.key_type.rune_ref_tag not in allowed_ref_types.get(
236-
property_nm, {}):
241+
if (ref.key_type.rune_ref_tag not in allowed_ref_types.get(
242+
property_nm, {}) and not _replaceable(old_val)):
237243
raise ValueError(f'Ref of type {ref.key_type} '
238244
f'not allowed for {property_nm}. Allowed types '
239245
f'are: {allowed_ref_types.get(property_nm, {})}')
@@ -245,18 +251,17 @@ def _bind_property_to(self, property_nm: str, ref: Reference):
245251
raise ValueError("Can't set reference. Incompatible types: "
246252
f"expected {allowed_type}, "
247253
f"got {ref.target.__class__}")
254+
248255
refs = self.__dict__.setdefault(REFS_CONTAINER, {})
249256
if property_nm not in refs:
250257
# not a reference - check if allowed to replace with one
251-
old_val = getattr(self, property_nm)
252-
if not isinstance(
253-
old_val,
254-
(BaseMetaDataMixin, UnresolvedReference, Reference)):
258+
if not _replaceable(old_val):
255259
raise ValueError(f'Property {property_nm} of type '
256260
f"{type(old_val)} can't be a reference")
257261
# pylint: disable=protected-access
258262
if isinstance(old_val, BaseMetaDataMixin):
259263
old_val._check_props_allowed({ref.key_type.rune_ref_tag: ''})
264+
260265
# setattr(self, property_nm, ref.target) # nope - need to avoid here!
261266
self.__dict__[property_nm] = ref.target # NOTE: avoid here setattr
262267
refs[property_nm] = (ref.target_key, ref.key_type)

0 commit comments

Comments
 (0)