Source code for regolith.chained_db

"""Base class for chaining DBs

ChainDBSingleton
Copyright 2015-2016, the xonsh developers
"""

import itertools

from collections import ChainMap
from collections.abc import MutableMapping


[docs]class ChainDBSingleton(object): """Singleton for representing when no default value is given.""" __inst = None def __new__(cls): if ChainDBSingleton.__inst is None: ChainDBSingleton.__inst = object.__new__(cls) return ChainDBSingleton.__inst
Singleton = ChainDBSingleton()
[docs]class ChainDB(ChainMap): """ A ChainMap who's ``_getitem__`` returns either a ChainDB or the result""" def __getitem__(self, key): res = None results = [] # Try to get all the data from all the mappings for mapping in self.maps: results.append(mapping.get(key, Singleton)) # if all the results are mapping create a ChainDB if all([isinstance(result, MutableMapping) for result in results]): for result in results: if res is None: res = ChainDB(result) else: res.maps.append(result) elif all([isinstance(result, list) for result in results]): return list(itertools.chain(*results)) elif all([isinstance(result, (list, ChainDBSingleton)) for result in results]): for result in results[::-1]: if isinstance(result, ChainDBSingleton): results.remove(result) if len(results) != 0: return list(itertools.chain(*results)) else: raise KeyError("{} is none of the current mappings".format(key)) else: for result in reversed(results): if result is not Singleton: return result raise KeyError("{} is none of the current mappings".format(key)) return res def __setitem__(self, key, value): if key not in self: super().__setitem__(key, value) else: res = None results = [] # Try to get all the data from all the mappings for mapping in reversed(self.maps): if key in mapping: mapping[key] = value
def _convert_to_dict(cm): if isinstance(cm, (ChainMap, ChainDB)): r = {} for k, v in cm.items(): r[k] = _convert_to_dict(v) return r else: return cm