1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556 |
- import collections
- import itertools
- # from jaraco.collections 3.5.1
- class DictStack(list, collections.abc.Mapping):
- """
- A stack of dictionaries that behaves as a view on those dictionaries,
- giving preference to the last.
- >>> stack = DictStack([dict(a=1, c=2), dict(b=2, a=2)])
- >>> stack['a']
- 2
- >>> stack['b']
- 2
- >>> stack['c']
- 2
- >>> len(stack)
- 3
- >>> stack.push(dict(a=3))
- >>> stack['a']
- 3
- >>> set(stack.keys()) == set(['a', 'b', 'c'])
- True
- >>> set(stack.items()) == set([('a', 3), ('b', 2), ('c', 2)])
- True
- >>> dict(**stack) == dict(stack) == dict(a=3, c=2, b=2)
- True
- >>> d = stack.pop()
- >>> stack['a']
- 2
- >>> d = stack.pop()
- >>> stack['a']
- 1
- >>> stack.get('b', None)
- >>> 'c' in stack
- True
- """
- def __iter__(self):
- dicts = list.__iter__(self)
- return iter(set(itertools.chain.from_iterable(c.keys() for c in dicts)))
- def __getitem__(self, key):
- for scope in reversed(tuple(list.__iter__(self))):
- if key in scope:
- return scope[key]
- raise KeyError(key)
- push = list.append
- def __contains__(self, other):
- return collections.abc.Mapping.__contains__(self, other)
- def __len__(self):
- return len(list(iter(self)))
|