Add metaclass capable of building instances from class name string

This commit is contained in:
Kristóf Tóth 2019-08-29 12:03:14 +02:00
parent 80eca7e322
commit d9bcfb3705
3 changed files with 65 additions and 0 deletions

View File

@ -0,0 +1 @@
from .type_id_registry import TypeIdREgistryMixin

View File

@ -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)

View File

@ -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}!')