Source code for i3pystatus.core.imputil
import inspect
import types
from importlib import import_module
from i3pystatus.core.exceptions import ConfigAmbigiousClassesError, ConfigInvalidModuleError
[docs]class ClassFinder:
"""Support class to find classes of specific bases in a module"""
def __init__(self, baseclass):
self.baseclass = baseclass
[docs] def predicate_factory(self, module):
def predicate(obj):
return (
inspect.isclass(obj)
and issubclass(obj, self.baseclass)
and obj.__module__ == module.__name__
)
return predicate
[docs] def get_matching_classes(self, module):
# Transpose [ (name, list), ... ] to ( [name, ...], [list, ...] )
classes = list(zip(*inspect.getmembers(module, self.predicate_factory(module))))
return classes[1] if classes else []
[docs] def get_class(self, module):
classes = self.get_matching_classes(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]
[docs] def get_module(self, module):
return import_module("i3pystatus.{mod}".format(mod=module))
[docs] 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 inspect.isclass(module) and issubclass(module, self.baseclass):
return module(*args, **kwargs)
elif args or kwargs:
raise ValueError(
"Additional arguments are invalid if 'module' is already an object")
return module