Source code for morfdict.models

from os import path
from importlib import import_module


class NoDefault:
    pass


[docs]class MorfDict(dict): def __init__(self, data={}, morf=None): """ :param data: dict of normal data :param morf: dict of morf methods """ super(MorfDict, self).__init__() self._morf = morf or {} self._parents = [] for name, value in data.items(): self[name] = value def __getitem__(self, key): left, right = self._split_key(key) value = self._get_from_self_or_parent(left) if right: value = value[right] method = self._morf.get(key, self._default_morf) return method(self, value) def _split_key(self, huge_key): try: left, right = huge_key.split(':', 1) return left, right except: return huge_key, None def _raw_get(self, key): return super().__getitem__(key) def _get_from_self_or_parent(self, key): for obj in [super(MorfDict, self)] + self._parents: try: return obj.__getitem__(key) except KeyError: continue raise KeyError(key)
[docs] def append_parent(self, parent, key=None): """Add parent to this object.""" self._parents.append(parent) if key: parent[key] = self
def _default_morf(self, obj, value): return value def __setitem__(self, key, value): def convert_dict_to_morfdict_if_avalible(value): if type(value) is dict: return self.__class__(value) return value def append_parent_if_avalible(value): if isinstance(value, MorfDict): value.append_parent(self) def make_set(key, value): return super(MorfDict, self).__setitem__(key, value) def set_child_morfdict(left, right, value): # if there is key with ':' it should make child morf dict and # insert data to it if left not in self: data = self.__class__() data.append_parent(self) else: data = self[left] data[right] = value return make_set(left, data) value = convert_dict_to_morfdict_if_avalible(value) append_parent_if_avalible(value) left, right = self._split_key(key) if right is None: return make_set(key, value) else: return set_child_morfdict(left, right, value)
[docs] def set_morf(self, key, morf): """Set morf method for this key.""" self._morf[key] = morf
[docs] def del_morf(self, key): """Delete morf method for this key.""" self._morf.pop(key)
[docs] def get_morf(self, key): """Get morf method for this key.""" return self._morf[key]
[docs] def to_dict(self): """Create simple dict object from this object.""" data = {} for key in list(self): value = self[key] if isinstance(value, MorfDict): value = value.to_dict() data[key] = value return data
def get(self, key, default=None): try: return self[key] except KeyError as error: if key == error.args[0] and default is not NoDefault: return default else: raise def items(self): for key in self.keys(): try: yield (key, self[key]) except KeyError: continue def merge(self, data): for key in data.keys(): value = data._raw_get(key) if isinstance(value, MorfDict): if key in self: self[key].merge(value) else: self[key] = value else: self[key] = value self._parents += data._parents
[docs]class StringDict(MorfDict): """Class which tries to interpolate itself on morf.""" def _default_morf(self, obj, value): if type(value) is str: return value % self else: return value
[docs]class PathDict(StringDict): """Class designed to store paths.""" def _default_morf(self, obj, values): if type(values) in (list, tuple): parsed_values = [] for value in values: parsed_values.append( value % self ) return path.join(*parsed_values) else: return values def __setitem__(self, key, value): if type(value) is str: value = [value, ] return super(PathDict, self).__setitem__(key, value)
[docs] def set_path(self, name, dirname, basename): """Sets path. :param name: name of path :param dirname: parent name of path :param basename: relative path """ if type(basename) not in (list, tuple): basename = [basename] if dirname is None: self[name] = basename else: self[name] = ['%%(%s)s' % (dirname,)] + basename
def get_path_dotted(self, module): args = module.split(':') module = import_module(args[0]) if args[1:]: dirpath = path.dirname(module.__file__) return path.join(dirpath, *args[1:]) else: return module.__file__