feat(base object): enforce unique speckle_type value

It was possible to override the builint types with a duplicate speckle_type, either via a duplicate
class name of an explicit speckle_type definition. It is now checked before registering the new type
in the subclass registry, and a meaningful error is thrown.
This commit is contained in:
Gergő Jedlicska
2021-02-13 14:45:14 +01:00
parent 1114b210f9
commit 4933ca4abf
2 changed files with 26 additions and 10 deletions
+20 -8
View File
@@ -30,11 +30,12 @@ class _RegisteringBase(BaseModel):
**kwargs: Dict[str, Any],
):
# this requires some validation, there is nothing blocking identical keys...
# if speckle_type in cls._type_registry:
# raise ValueError(
# f"The speckle_type: {speckle_type} is already registered. "
# f"Please choose a different type name."
# )
if speckle_type in cls._type_registry:
raise ValueError(
f"The speckle_type: {speckle_type} is already registered for type: "
f"{cls._type_registry[speckle_type].__name__}. "
f"Please choose a different type name."
)
cls.speckle_type = speckle_type or cls.__name__
cls._type_registry[cls.speckle_type] = cls # type: ignore
super().__init_subclass__(**kwargs)
@@ -49,9 +50,20 @@ class Base(_RegisteringBase):
_chunk_size_default: int = 1000
_detachable: List[str] = [] # list of defined detachable props
def __init__(self, **kwargs: Dict[str, Any]) -> None:
super().__init__()
self.__dict__.update(kwargs)
# def __init__(self, **kwargs: Dict[str, Any]) -> None:
# super().__init__(**kwargs)
# """
# based on my testing, the __dict__ update is not required,
# even works with extra init arguments, that are not part of the basic object
# definition. It is even possible, that the custom __init__ definition could go
# away all together
# >>> base = Base(foo="bar")
# >>> base.foo
# "bar"
# """
# # self.__dict__.update(kwargs)
def __repr__(self) -> str:
return (
+6 -2
View File
@@ -37,5 +37,9 @@ def test_fake_base_serialization() -> None:
deserialized = operations.deserialize(serialized)
assert fake_model.get_id() == deserialized.get_id()
# assert isinstance(base.test_bases[0], Base)
# assert base["@detach"].name == deserialized["@detach"].name
def test_duplicate_speckle_type_raises_error():
with pytest.raises(ValueError):
class NaughtyClass(Base, speckle_type="Base"):
"""This class has a speckle_type that is already taken."""