Mercurial > hgrepos > Python > libs > ConfigMix
view configmix/config.py @ 26:1b8d5c9d294f v0.1
+++++ v0.1
| author | Franz Glasner <f.glasner@feldmann-mg.com> |
|---|---|
| date | Thu, 10 Mar 2016 17:30:55 +0100 |
| parents | baf862cb4860 |
| children | 17af7a78710c |
line wrap: on
line source
# -*- coding: utf-8 -*- r"""The unified configuration dictionary with attribute support or variable substitution. """ from __future__ import division, absolute_import, print_function try: from collections import OrderedDict as ConfigurationBase except ImportError: try: from ordereddict import OrderedDict as ConfigurationBase except ImportError: ConfigurationBase = dict from .variables import lookup_varns, lookup_filter from .compat import u __all__ = ["Configuration"] _MARKER = object() class _AttributeDict(ConfigurationBase): def __getattr__(self, name): try: v = self[name] except KeyError: raise AttributeError("%s has no attribute %r" % (type(self), name)) else: # Wrap a dict into another dict with attribute access support if isinstance(v, dict): return AttributeDict(v) else: return v class Configuration(_AttributeDict): """The configuration dictionary with attribute support or variable substitution. .. note:: When retriving by attribute names variables will *not* substituted. """ def getvar(self, varname, default=_MARKER): """Get a variable of the form ``[[ns1.]ns2.]name`` - including variables from other namespaces. No variable expansion is done and no filters are applied. """ varns, varname = self._split_ns(varname) try: if not varns: lookupfn = self._lookupvar else: lookupfn = lookup_varns(varns) varvalue = lookupfn(varname) except KeyError: if default is _MARKER: raise KeyError("Variable %r not found" % varname) else: return default else: return varvalue def getvar_s(self, varname, default=_MARKER): """Get a variable - including variables from other namespaces. Variables will be substituted recursively in the result. """ try: obj = self.getvar(varname) return self.substitute_variables_in_obj(obj) except KeyError: if default is _MARKER: raise else: return default def _split_ns(self, s): nameparts = s.split(':', 1) if len(nameparts) == 1: return (None, s, ) else: return (nameparts[0], nameparts[1], ) def _split_filters(self, s): nameparts = s.split('|') if len(nameparts) == 1: return (s, [], ) else: return (nameparts[0].rstrip(), nameparts[1:], ) def _lookupvar(self, key, default=_MARKER): """Lookup a variable. If no default is given an unexisting `key` raises a `KeyError` else `default` is returned. """ parts = key.split('.') try: v = self[parts[0]] for p in parts[1:]: v = v[p] except KeyError: if default is _MARKER: raise KeyError("Configuration variable %r not found" % key) else: return default return v # Speed _TEXTTYPE = type(u("")) def substitute_variables_in_obj(self, obj): """Recursively expand variables in the object tree `obj`.""" if isinstance(obj, self._TEXTTYPE): # a string - really replace the value return self.expand_variable(obj) elif isinstance(obj, list): return [self.substitute_variables_in_obj(i) for i in obj] elif isinstance(obj, tuple): tmp = [self.substitute_variables_in_obj(i) for i in obj] return type(obj)(tmp) elif isinstance(obj, dict): newdict = type(obj)() for k in obj: newdict[k] = self.substitute_variables_in_obj(obj[k]) return newdict elif isinstance(obj, set): newset = type(obj)() for i in obj: newset.add(self.substitute_variables_in_obj(i)) else: return obj # Speed _STARTTOK = u(b"{{") _ENDTOK = u(b"}}") def expand_variable(self, s): """Expand variables in a single string""" start = s.find(self._STARTTOK, 0) while start != -1: end = s.find(self._ENDTOK, start) if end < 0: return s varname, filters = self._split_filters(s[start+2:end]) varvalue = self._apply_filters(filters, self.getvar_s(varname)) if varvalue is None: varvalue = u("") replaced = u(b"{0}{1}").format(s[:start], varvalue) s = u(b"{0}{1}").format(replaced, s[end+2:]) # don't re-evaluate because `self.getvar_s()` expands already start = s.find(self._STARTTOK, len(replaced)) return s def _apply_filters(self, filters, value): for name in filters: try: filterfn = lookup_filter(name) except KeyError: raise NameError("Filter %r not found" % name) else: value = filterfn(self, value) return value
