Source code for pyqos.config

#!/usr/bin/env python3
# Author: Anthony Ruhier

import errno
import importlib
import logging
import os
import types


[docs]class Config(dict): """ Works like a dict but can be filled directly from a python configuration file. Inspired from the Flask Config class (a part of their code has been copied here). Only uppercase keys are added to the config. This makes it possible to use lowercase values in the config file for temporary values that are not added to the config or to define the config keys in the same file that implements the application. :param root_path: path to which files are read relative from. When the config object is created by the application, this is the application's :attr:`~pyqos.PyQoS.root_path`. :param defaults: an optional dictionary of default values """ def __init__(self, root_path, defaults=None): dict.__init__(self, defaults or {}) self.root_path = root_path or "./" self.refresh_global_logger_lvl() def refresh_global_logger_lvl(self): if self["DEBUG"] or self["DRYRUN"]: logging.getLogger("pyqos").setLevel(logging.DEBUG)
[docs] def from_pyfile(self, filename, silent=False): """ Updates the values in the config from a Python file. This function behaves as if the file was imported as module with the :meth:`from_object` function. :param filename: the filename of the config. This can either be an absolute filename or a filename relative to the root path. :param silent: set to ``True`` if you want silent failure for missing files. """ filename = os.path.join(self.root_path, filename) d = types.ModuleType('config') d.__file__ = filename try: with open(filename) as config_file: exec(compile(config_file.read(), filename, 'exec'), d.__dict__) except IOError as e: if silent and e.errno in (errno.ENOENT, errno.EISDIR): return False e.strerror = 'Unable to load configuration file (%s)' % e.strerror raise self.from_object(d) return True
[docs] def from_object(self, obj): """ Updates the values from the given object. An object can be of one of the following two types: - a string: in this case the object with that name will be imported - an actual object reference: that object is used directly Objects are usually either modules or classes. Just the uppercase variables in that object are stored in the config. Example usage:: app.config.from_object('yourapplication.default_config') from yourapplication import default_config app.config.from_object(default_config) You should not use this function to load the actual configuration but rather configuration defaults. The actual config should be loaded with :meth:`from_pyfile` and ideally from a location not within the package because the package might be installed system wide. :param obj: an import name or object """ if isinstance(obj, str): obj = importlib.import_module(obj) for key in dir(obj): if key.isupper(): self[key] = getattr(obj, key)
[docs]class ConfigAttribute(object): """ Makes an attribute forward to the config Again, copied from the Flask project """ def __init__(self, name, get_converter=None): self.__name__ = name self.get_converter = get_converter def __get__(self, obj, type=None): if obj is None: return self rv = obj.config[self.__name__] if self.get_converter is not None: rv = self.get_converter(rv) return rv def __set__(self, obj, value): # When setting the log level, change the global logger level obj.config[self.__name__] = value obj.config.refresh_global_logger_lvl()