Source code for xobox.utils.loader

# -*- coding: utf-8 -*-

"""
    xobox.utils.loader
    ~~~~~~~~~~~~~~~~~~
    :copyright: Copyright 2017 by the Stormrose Project team, see AUTHORS.
    :license: MIT License, see LICENSE for details.
"""


import importlib
import os
from xobox.utils import filters


[docs]def detect_class_modules(mod, parent=object): """ Detect available class modules or packages and return a dictionary of valid class names, referring to the module they are contained within. :param str mod: the module or package to be scanned for classes :param parent: the class potential candidates must be derived off :returns: dictionary of detected classes, mapping the class name to the module name in which the class has been detected """ # initialise result dictionary result = {} candidates = [] # get a list of all files and directories inside the module try: package_instance = importlib.import_module(mod) except ImportError: return result pkg_file = os.path.splitext(package_instance.__file__) if pkg_file[0][-8:] == '__init__' and pkg_file[1][1:3] == 'py': # it's a package, so we have to look for modules gen_dir = os.listdir(os.path.dirname(os.path.realpath(package_instance.__file__))) # only consider modules and packages, and exclude the base module for file_candidate in filter(filters.modules, gen_dir): # Python files are modules; the name needs to be without file ending if file_candidate[-3:] == '.py': file_candidate = file_candidate[:-3] # try if the detected package or module can be imported try: class_module_candidate = importlib.import_module('.'.join([mod, file_candidate])) except ImportError: class_module_candidate = None # if the module or module could be imported, append it to the list of candidate modules. if class_module_candidate: candidates.append(class_module_candidate) else: candidates.append(package_instance) # test if any of the candidates contain # classes derived from the parent class for candidate in candidates: for member_candidate in filter(filters.members, dir(candidate)): try: if issubclass(getattr(candidate, member_candidate), parent) \ and getattr(candidate, member_candidate).__name__ != parent.__name__: result[member_candidate] = candidate.__name__ except TypeError: pass # return the dictionary return result
[docs]def load_member(mod, member): """ Load a member (function, class, ...) from a module and return it :param str mod: the module or package name where the class should be loaded from :param str member: the name of the member to be loaded :returns: reference to the loaded member (i. e. class or function pointer) """ try: mod = importlib.import_module(mod) except ImportError: return None try: result = getattr(mod, member) except AttributeError: return None return result