diff options
Diffstat (limited to 'pecan/configuration.py')
-rw-r--r-- | pecan/configuration.py | 254 |
1 files changed, 0 insertions, 254 deletions
diff --git a/pecan/configuration.py b/pecan/configuration.py deleted file mode 100644 index 6260723..0000000 --- a/pecan/configuration.py +++ /dev/null @@ -1,254 +0,0 @@ -import re -import inspect -import os -import sys - -import six - -if six.PY3: - from importlib.machinery import SourceFileLoader -else: - import imp - - -IDENTIFIER = re.compile(r'[a-z_](\w)*$', re.IGNORECASE) - -DEFAULT = { - # Server Specific Configurations - 'server': { - 'port': '8080', - 'host': '0.0.0.0' - }, - - # Pecan Application Configurations - 'app': { - 'root': None, - 'modules': [], - 'static_root': 'public', - 'template_path': '', - 'force_canonical': True - } -} - - -class ConfigDict(dict): - pass - - -class Config(object): - ''' - Base class for Pecan configurations. - - Create a Pecan configuration object from a dictionary or a - filename. - - :param conf_dict: A python dictionary to use for the configuration. - :param filename: A filename to use for the configuration. - ''' - - def __init__(self, conf_dict={}, filename=''): - - self.__values__ = {} - self.__file__ = filename - self.update(conf_dict) - - def empty(self): - self.__values__ = {} - - def update(self, conf_dict): - ''' - Updates this configuration with a dictionary. - - :param conf_dict: A python dictionary to update this configuration - with. - ''' - - if isinstance(conf_dict, dict): - iterator = six.iteritems(conf_dict) - else: - iterator = iter(conf_dict) - - for k, v in iterator: - if not IDENTIFIER.match(k): - raise ValueError('\'%s\' is not a valid indentifier' % k) - - cur_val = self.__values__.get(k) - - if isinstance(cur_val, Config): - cur_val.update(conf_dict[k]) - else: - self[k] = conf_dict[k] - - def get(self, attribute, default=None): - try: - return self[attribute] - except KeyError: - return default - - def __dictify__(self, obj, prefix): - ''' - Private helper method for to_dict. - ''' - for k, v in obj.copy().items(): - if prefix: - del obj[k] - k = "%s%s" % (prefix, k) - if isinstance(v, Config): - v = self.__dictify__(dict(v), prefix) - obj[k] = v - return obj - - def to_dict(self, prefix=None): - ''' - Converts recursively the Config object into a valid dictionary. - - :param prefix: A string to optionally prefix all key elements in the - returned dictonary. - ''' - - conf_obj = dict(self) - return self.__dictify__(conf_obj, prefix) - - def __getattr__(self, name): - try: - return self.__values__[name] - except KeyError: - msg = "'pecan.conf' object has no attribute '%s'" % name - raise AttributeError(msg) - - def __getitem__(self, key): - return self.__values__[key] - - def __setitem__(self, key, value): - if isinstance(value, dict) and not isinstance(value, ConfigDict): - if value.get('__force_dict__'): - del value['__force_dict__'] - self.__values__[key] = ConfigDict(value) - else: - self.__values__[key] = Config(value, filename=self.__file__) - elif isinstance(value, six.string_types) and '%(confdir)s' in value: - confdir = os.path.dirname(self.__file__) or os.getcwd() - self.__values__[key] = value.replace('%(confdir)s', confdir) - else: - self.__values__[key] = value - - def __iter__(self): - return six.iteritems(self.__values__) - - def __dir__(self): - """ - When using dir() returns a list of the values in the config. Note: - This function only works in Python2.6 or later. - """ - return list(self.__values__.keys()) - - def __repr__(self): - return 'Config(%s)' % str(self.__values__) - - -def conf_from_file(filepath): - ''' - Creates a configuration dictionary from a file. - - :param filepath: The path to the file. - ''' - - abspath = os.path.abspath(os.path.expanduser(filepath)) - conf_dict = {} - if not os.path.isfile(abspath): - raise RuntimeError('`%s` is not a file.' % abspath) - - # First, make sure the code will actually compile (and has no SyntaxErrors) - with open(abspath, 'rb') as f: - compiled = compile(f.read(), abspath, 'exec') - - # Next, attempt to actually import the file as a module. - # This provides more verbose import-related error reporting than exec() - absname, _ = os.path.splitext(abspath) - basepath, module_name = absname.rsplit(os.sep, 1) - if six.PY3: - SourceFileLoader(module_name, abspath).load_module(module_name) - else: - imp.load_module( - module_name, - *imp.find_module(module_name, [basepath]) - ) - - # If we were able to import as a module, actually exec the compiled code - exec(compiled, globals(), conf_dict) - conf_dict['__file__'] = abspath - - return conf_from_dict(conf_dict) - - -def get_conf_path_from_env(): - ''' - If the ``PECAN_CONFIG`` environment variable exists and it points to - a valid path it will return that, otherwise it will raise - a ``RuntimeError``. - ''' - config_path = os.environ.get('PECAN_CONFIG') - if not config_path: - error = "PECAN_CONFIG is not set and " \ - "no config file was passed as an argument." - elif not os.path.isfile(config_path): - error = "PECAN_CONFIG was set to an invalid path: %s" % config_path - else: - return config_path - - raise RuntimeError(error) - - -def conf_from_dict(conf_dict): - ''' - Creates a configuration dictionary from a dictionary. - - :param conf_dict: The configuration dictionary. - ''' - conf = Config(filename=conf_dict.get('__file__', '')) - - for k, v in six.iteritems(conf_dict): - if k.startswith('__'): - continue - elif inspect.ismodule(v): - continue - - conf[k] = v - return conf - - -def initconf(): - ''' - Initializes the default configuration and exposes it at - ``pecan.configuration.conf``, which is also exposed at ``pecan.conf``. - ''' - return conf_from_dict(DEFAULT) - - -def set_config(config, overwrite=False): - ''' - Updates the global configuration. - - :param config: Can be a dictionary containing configuration, or a string - which represents a (relative) configuration filename. - ''' - - if config is None: - config = get_conf_path_from_env() - - # must be after the fallback other a bad fallback will incorrectly clear - if overwrite is True: - _runtime_conf.empty() - - if isinstance(config, six.string_types): - config = conf_from_file(config) - _runtime_conf.update(config) - if config.__file__: - _runtime_conf.__file__ = config.__file__ - elif isinstance(config, dict): - _runtime_conf.update(conf_from_dict(config)) - else: - raise TypeError('%s is neither a dictionary or a string.' % config) - - -_runtime_conf = initconf() |