Source code for authnzerver.modtools

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

"""This contains functions to dynamically import modules and get Python objects.

"""

#############
## LOGGING ##
#############

import logging

LOGGER = logging.getLogger(__name__)

LOGDEBUG = LOGGER.debug
LOGINFO = LOGGER.info
LOGWARNING = LOGGER.warning
LOGERROR = LOGGER.error
LOGEXCEPTION = LOGGER.exception

#############
## IMPORTS ##
#############

import sys
import importlib
import os.path


###############
## FUNCTIONS ##
###############


[docs]def module_from_string(module, force_reload=False): """This imports the module specified. Used to dynamically import Python modules. Parameters ---------- module : str This is either: - a Python module import path, e.g. 'concurrent.futures' or - a path to a Python file, e.g. '~/authnzerver/authnzerver/main.py' force_reload : bool If True, will reload a previous imported module even if it's been previously imported. This is useful to pick up changes in Python module files used as program config files. Returns ------- Python module This returns a Python module if it's able to successfully import it. Notes ----- Hypens are not allowed in module filenames. """ try: if os.path.exists(module): if "~" in module: module = os.path.expanduser(module) sys.path.append(os.path.dirname(module)) module_import_path = os.path.basename(module.replace(".py", "")) if "-" in module_import_path or " " in module_import_path: LOGERROR( "Can't import the requested module." "Spaces or the character '-' are not allowed in a " "Python module name. " "Try using the '_' character " "instead if you want spaces." ) return False # check if the module has already been imported if module_import_path in sys.modules and force_reload: # get the module object imported_module = importlib.import_module(module_import_path) # call reload on the module object importedok = importlib.reload(imported_module) else: importedok = importlib.import_module(module_import_path) else: if module in sys.modules and force_reload: importedok = importlib.reload(module) else: importedok = importlib.import_module(module) except Exception: LOGEXCEPTION( "Could not import the module: %s. " "Check the file path or fully qualified module name?" % (module,) ) importedok = False return importedok
[docs]def object_from_string(objectpath, force_reload=False): """This returns a Python object pointed to by the given string. An object can be any valid Python object. One of the main uses for this function is to dynamically load Python functions from a module given its file path on disk or a fully qualified module string. The string should be in one of the forms below: - fully qualified module name and object name, e.g.:: 'authnzerver.confvars.CONF' -> gets the CONF dict 'sqlalchemy.dialects.postgresql.JSONB' -> gets the JSONB class 'scipy.ndimage.convolve' -> gets the convolve() function - path to a module on disk and the object name separated by '::', e.g.:: '~/authnzerver/authnzerver/actions/user.py::create_new_user' '~/authzerver/authnzerver/authdb.py::Users' (This is similar to the format used by pytest.) """ if "::" in objectpath: pymod, pyobject = objectpath.split("::") else: splitstr = objectpath.split(".") pymod, pyobject = ".".join(splitstr[:-1]), splitstr[-1] imported_module = module_from_string(pymod, force_reload=force_reload) if imported_module is not False: return getattr(imported_module, pyobject) else: return None