diff --git a/tfw/internals/event_handling/type_id_registry/__init__.py b/tfw/internals/event_handling/type_id_registry/__init__.py new file mode 100644 index 0000000..6786ca7 --- /dev/null +++ b/tfw/internals/event_handling/type_id_registry/__init__.py @@ -0,0 +1 @@ +from .type_id_registry import TypeIdREgistryMixin diff --git a/tfw/internals/event_handling/type_id_registry/test_type_id_registry.py b/tfw/internals/event_handling/type_id_registry/test_type_id_registry.py new file mode 100644 index 0000000..617d695 --- /dev/null +++ b/tfw/internals/event_handling/type_id_registry/test_type_id_registry.py @@ -0,0 +1,43 @@ +import pytest + +from .type_id_registry import TypeIdREgistryMixin + + +def test_registry(): + class A(TypeIdREgistryMixin): + _type_id_registry = {} + class B(A): + pass + class C(A): + pass + + # pylint: disable=protected-access + assert A._type_id_registry['B'] == B + assert A._type_id_registry['C'] == C + + +def test_build_by_type_id(): + class D(TypeIdREgistryMixin): + _type_id_registry = {} + built = [] + class E(D): + def __init__(self): + built.append(self) + class F(D): + def __init__(self): + built.append(self) + raise RuntimeError('cica') + class H(E): + pass + + D.build_type('E') + assert isinstance(built[0], E) + + with pytest.raises(RuntimeError) as err: + D.build_type('F') + assert err.value.args[0] == 'cica' + assert isinstance(built[1], F) + + D.build_type('H') + assert isinstance(built[2], H) + assert isinstance(built[2], E) diff --git a/tfw/internals/event_handling/type_id_registry/type_id_registry.py b/tfw/internals/event_handling/type_id_registry/type_id_registry.py new file mode 100644 index 0000000..2737480 --- /dev/null +++ b/tfw/internals/event_handling/type_id_registry/type_id_registry.py @@ -0,0 +1,21 @@ +from abc import ABCMeta +from contextlib import suppress + + +class TypeIdREgistryMeta(ABCMeta): + def __init__(cls, name, bases, attrs): + with suppress(AttributeError): + if cls.__name__ in cls._type_id_registry: + raise RuntimeError('Type id must be unique!') + cls._type_id_registry[cls.__name__] = cls + super().__init__(name, bases, attrs) + + +class TypeIdREgistryMixin(metaclass=TypeIdREgistryMeta): + @classmethod + def build_type(cls, type_id, *args, **kwargs): + try: + instance_type = cls._type_id_registry[type_id] + return instance_type(*args, **kwargs) + except KeyError: + raise RuntimeError(f'No type with id {type_id}!')