Source code for pycmor.core.factory
import inspect
[docs]
def create_factory(klass):
"""Factory factory""" # factory for factories because why not
class KlassFactory:
@staticmethod
def _retrieve_from_registry(subclass_type):
if subclass_type not in klass._registry:
raise ValueError(
f"No subclass {subclass_type} registered for {klass.__name__}"
)
return klass._registry[subclass_type]
@staticmethod
def get(subclass_type):
return KlassFactory._retrieve_from_registry(subclass_type)
# #####################################################################
# TODO(PG): Actually remove these if they are not needed
#
# These might just go away if the interspection method works as expected
# and we can call the "generated" from_foo methods directly from the
# factory.
#
# #####################################################################
@staticmethod
def create(subclass_type, **kwargs):
klass_instance = KlassFactory._retrieve_from_registry(subclass_type)
return klass_instance(**kwargs)
@staticmethod
def from_dict(subclass_type, data):
klass_instance = KlassFactory._retrieve_from_registry(subclass_type)
return klass_instance.from_dict(data)
# FIXME(PG): This doesn't work yet...
@classmethod
def _introspect_and_create_methods(cls, klass):
for name, method in inspect.getmembers(klass, predicate=inspect.isfunction):
if isinstance(method, property):
continue
if name.startswith("__") and name.endswith("__"):
continue # Skip special methods
def create_factory_method(method_name):
@staticmethod
def factory_method(subclass_type, *args, **kwargs):
klass_instance = KlassFactory._retrieve_from_registry(
subclass_type
)
return getattr(klass_instance, method_name)(*args, **kwargs)
return factory_method
setattr(cls, name, create_factory_method(name))
return cls
# Dynamically set the class name:
KlassFactory.__name__ = f"{klass.__name__}Factory"
KlassFactory.__repr__ = lambda self: f"{KlassFactory.__name__}()"
# Set constructor methods
# factory = KlassFactory._introspect_and_create_methods(klass)
return KlassFactory