46 lines
1.6 KiB
Python
46 lines
1.6 KiB
Python
import inspect
|
|
import types
|
|
from importlib import import_module
|
|
|
|
class ClassFinder:
|
|
"""Support class to find classes of specific bases in a module"""
|
|
|
|
def __init__(self, baseclass):
|
|
self.baseclass = baseclass
|
|
|
|
def predicate_factory(self, module):
|
|
def predicate(obj):
|
|
return (
|
|
inspect.isclass(obj) and
|
|
issubclass(obj, self.baseclass) and
|
|
obj.__module__ == module.__name__
|
|
)
|
|
return predicate
|
|
|
|
def search_module(self, module):
|
|
return list(zip(*inspect.getmembers(module, self.predicate_factory(module))))[1]
|
|
|
|
def get_class(self, module):
|
|
classes = self.search_module(module)
|
|
|
|
if len(classes) > 1:
|
|
# If there are multiple Module clases bundled in one module,
|
|
# well, we can't decide for the user.
|
|
raise ConfigAmbigiousClassesError(module.__name__, classes)
|
|
elif not classes:
|
|
raise ConfigInvalidModuleError(module.__name__)
|
|
|
|
return classes[0]
|
|
|
|
def get_module(self, module):
|
|
return import_module("i3pystatus.{mod}".format(mod=module))
|
|
|
|
def instanciate_class_from_module(self, module, *args, **kwargs):
|
|
if isinstance(module, types.ModuleType):
|
|
return self.get_class(module)(*args, **kwargs)
|
|
elif isinstance(module, str):
|
|
return self.instanciate_class_from_module(self.get_module(module), *args, **kwargs)
|
|
elif args or kwargs:
|
|
raise ValueError("Additional arguments are invalid if 'module' is already an object")
|
|
return module
|