Source code for metann.utils.containers

import collections
from collections import defaultdict
from itertools import count


[docs]class SubDict(collections.abc.MutableMapping): r""" Provide a sub dict **access** to a super dict. Args: super_dict (Mapping): The super dictionary where you want to take a sub dict keys (iterable): An iterable of keys according to which you want to access a sub dict keep_order (bool): If set to true the sub dict will keep the iteration order of the super dict when it is iterated. Default: True Examples: >>> super_dict = collections.OrderedDict({'a': 1, 'b': 2, 'c': 3}) >>> sub_dict = SubDict(super_dict, keys=['a', 'b']) """ def __init__(self, super_dict: collections.abc.Mapping, keys=[], keep_order=True): self.super_dict = super_dict self.sub_keys = set(keys) self.update_keys() self.keep_order = keep_order def __getitem__(self, item): if item in self.sub_keys: return self.super_dict.__getitem__(item) else: raise KeyError(item) def __setitem__(self, key, value): self.sub_keys.add(key) return self.super_dict.__setitem__(key, value) def __delitem__(self, key): self.sub_keys.remove(key) try: del self.super_dict[key] except KeyError: pass def __contains__(self, key): self.update_keys() return self.sub_keys.__contains__(key) def __iter__(self): if self.keep_order: for i in self.super_dict: if i in self.sub_keys: yield i else: for i in self.sub_keys: yield i def __len__(self): self.update_keys() return len(self.sub_keys) def __str__(self): return "SubDict("+str(list(self))+")"
[docs] def update_keys(self): r""" This method update the keys of the sub dict when the super dict is modified. .. note:: **Do not** call this method when you use the built-in method only. :return: """ self.sub_keys = self.sub_keys.intersection(self.super_dict.keys())
def _none_fun(*input): return None
[docs]class DefaultList(object): def __init__(self, factory=_none_fun, fill=None): self.store = defaultdict(factory) def __getitem__(self, item): if not isinstance(item, int) or item < 0: raise KeyError('index should be a non negative integer') return self.store[item] def __setitem__(self, key, value): if not isinstance(key, int) or key < 0: raise KeyError('index should be a non negative integer') self.store[key] = value def __iter__(self): for idx in count(0, 1): yield self.store[idx]
[docs] def fill(self, data: collections.abc.Iterable): for idx, value in enumerate(data): self.store[idx] = value
[docs]class MultipleList(object): def __init__(self, lst): self.lst = lst def __getitem__(self, item): if isinstance(item, collections.abc.Iterable): return [self.lst[i] for i in item] else: return self.lst[item] def __setitem__(self, key, value): if isinstance(key, collections.abc.Iterable): for k, v in zip(key, value): self.lst[k] = v else: self.lst[key] = value def __iter__(self): return iter(self.lst)