Example #1
0
 def __init__(self, node_name: valid_node_name, cage_name: valid_cage_name,
              cage_directory: os_path.isdir, log: callable, log_priority: int):
     self._node_name, self._cage_name = node_name, cage_name
     self._log, self._log_priority = log, log_priority
     self._cage_directory = cage_directory
     self._module_locator = ModuleLocator(self._cage_directory)
     self._lock, self._modules, self._loggers = Lock(), {}, {}
Example #2
0
class ModuleLoader:

    @typecheck
    def __init__(self, node_name: valid_node_name, cage_name: valid_cage_name,
                 cage_directory: os_path.isdir, log: callable, log_priority: int):
        self._node_name, self._cage_name = node_name, cage_name
        self._log, self._log_priority = log, log_priority
        self._cage_directory = cage_directory
        self._module_locator = ModuleLocator(self._cage_directory)
        self._lock, self._modules, self._loggers = Lock(), {}, {}

    ###################################

    class _Logger:

        def __init__(self, log, log_priority, src_module):
            self._log, self._log_priority = log, log_priority
            self._src_module = src_module

        def __call__(self, s, priority = None):
            try:
                if priority is None:
                    return self(s, priority = 4)
                elif priority <= self._log_priority:
                    while not isinstance(s, str):
                        try:
                            s = str(s)
                        except:
                            s = str(s.__class__)
                    request = getattr(current_thread(), "_request", None)
                    req_desc = request.description if request else ""
                    req_desc = " by {0:s}".format(req_desc) if req_desc else ""
                    if self._src_module:
                        line, func = extract_stack(None, 3)[-3][1:3]
                        s += " # {0:s}.py:{1:d} in {2:s}(){3:s}".\
                             format(self._src_module, line, func, req_desc)
                    elif req_desc:
                        s += " #{0:s}".format(req_desc)
                    self._log(s, priority = priority)
            except:
                pass # do nothing

        error = lambda self, s: self(s, priority = 1)
        message = lambda self, s: self(s, priority = 2)
        warning = lambda self, s: self(s, priority = 3)
        info = lambda self, s: self(s, priority = 5)
        debug = lambda self, s: self(s, priority = 6)

    def set_log_priority(self, log_priority):
        with self._lock:
            if self._log_priority != log_priority:
                self._log_priority = log_priority
                self._loggers.clear()

    ###################################

    def __getattr__(self, module_name, src_module = None):

        # special case #1: pmnc.log[.error|.message|.warning|.info|.debug](s)
        # I prefer to cache logger instances created for each module for two
        # reasons: (1) runtime exception safety and (2) performance

        if module_name == "log":
            with self._lock:
                logger = self._loggers.get(src_module)
                if logger is None:
                    logger = ModuleLoader._Logger(self._log, self._log_priority, src_module)
                    self._loggers[src_module] = logger
            return logger

        # special case #2: pmnc.request

        request = current_thread()._request

        if module_name == "request":
            return request

        # reserve a private namespace for modules

        if module_name.startswith("_"):
            raise InvalidModuleNameError("module name cannot start with underscore")

        # locate the file containing the required module

        module_filename = \
            self._module_locator.locate("{0:s}.py".format(module_name)) or \
            self._module_locator.locate("{0:s}.pyc".format(module_name))

        if module_filename is None:
            raise ModuleNotFoundError("file {0:s}.py was not found".format(module_name))

        # see if such module has already been loaded, create an empty object if it hasn't

        with self._lock:
            module = self._modules.get(module_name)
            if not module:
                module = Module(module_name, self)
                self._modules[module_name] = module

        # reload the module if necessary and return the proxy object

        return module.reload(module_filename, request, src_module)