i2.chain_map

Merge mappings

Marked for deprecation.

Functions

is_iterable(x)

Similar in nature to callable(), is_iterable returns True if an object is iterable, False if not.

is_mapping(x)

not_mapping(x)

unique_iter(src[, key])

Yield unique elements from the iterable, src, based on key, in the order in which they first appeared in src.

Classes

ChainMapTree(*maps)

Combine/overlay multiple hierarchical mappings.

class i2.chain_map.ChainMapTree(*maps)[source]

Bases: Mapping

Combine/overlay multiple hierarchical mappings. This efficiently merges multiple hierarchical (could be several layers deep) dictionaries, producing a new view into them that acts exactly like a merged dictionary, but without doing any copying. Because it doesn’t actually copy the data, it is intended to be used only with immutable mappings. It is safe to change leaf data values, and the results will be reflected here, but changing the structure of any of the trees will not work.

>>> base1 = {
...     'a1': 'base1.a1',
...     'a2': 'base1.a2',
...     'a3': {
...         'b1': 'base1.a3.b1',
...         'b2': 'base1.a3.b2',
...     },
... }
>>> base2 = {
...     'a2': 'base2.a2',
...     'a3': {
...         'b2': 'base2.a3.b2',
...         'b4': 'base2.a3.b4',
...     },
...     'a4': 'base2.a4',
... }
>>>
>>> cm = ChainMapTree(base1, base2)
>>> cm['a1']
'base1.a1'
>>> cm['a2']
'base1.a2'
>>> cm['a4']
'base2.a4'
>>> cm['a3']
ChainMapTree({'b1': 'base1.a3.b1', 'b2': 'base1.a3.b2'}, {'b2': 'base2.a3.b2', 'b4': 'base2.a3.b4'})
>>> cm['a3']['b1']
'base1.a3.b1'
>>> cm['a3']['b4']
'base2.a3.b4'
>>> cm = ChainMapTree(base2, base1)
>>> cm['a1']
'base1.a1'
>>> cm['a2']
'base2.a2'
>>> cm['a4']
'base2.a4'
>>> cm['a3']
ChainMapTree({'b2': 'base2.a3.b2', 'b4': 'base2.a3.b4'}, {'b1': 'base1.a3.b1', 'b2': 'base1.a3.b2'})
>>> cm['a3']['b2']
'base2.a3.b2'
>>> cm['a3']['b1']
'base1.a3.b1'
>>>
>>> # Let's do a ChainMapTree with THREE bases now!
>>> base3 = {
...     'a2': 'base3.a2',
...     'a3': {
...         'b2': 'base3.a3.b2',
...         'b4': 'base3.a3.b4',
...     },
...     'a4': 'base3.a4',
... }
>>> cm = ChainMapTree(base3, base2, base1)
>>> cm['a2']  # will get it from base3
'base3.a2'
>>> cm['a3']['b2']  # will get it from base3 (not base2)
'base3.a3.b2'
>>> cm['a3']['b1']  # will get it from base1 (since no one else has it)
'base1.a3.b1'

Based on: https://gist.github.com/Klortho/7d83975559bdcc47ac64fd7d877934f6

to_dict()[source]

Convert to dict

>>> a = {'a': {'x': 1, 'z': 3}, 'foo': "a's foo"}
>>> b = {'a': {'y': 222, 'z': 333}, 'foo': "b's foo"}
>>> cm = ChainMapTree(a, b)
>>> # It acts like a dict when you ask for items, but is not a dict. If you want a dict, do this:
>>> cm.to_dict()
{'a': {'x': 1, 'z': 3, 'y': 222}, 'foo': "a's foo"}
>>> # Compare to normal/flat/not-nested chaining:
>>> dict(a, **b)   # Note the precedence is the inverse of ChainMapTree!
{'a': {'y': 222, 'z': 333}, 'foo': "b's foo"}
>>>
>>> # See what you get if you specify b before a
>>> ChainMapTree(b, a).to_dict()
{'a': {'y': 222, 'z': 333, 'x': 1}, 'foo': "b's foo"}
>>> # Compare to normal/flat/not-nested chaining:
>>> dict(b, **a)  # Note the precedence is the inverse of ChainMapTree!
{'a': {'x': 1, 'z': 3}, 'foo': "a's foo"}
i2.chain_map.is_iterable(x)[source]

Similar in nature to callable(), is_iterable returns True if an object is iterable, False if not.

>>> is_iterable([])
True
>>> is_iterable(1)
False
i2.chain_map.unique_iter(src, key=None)[source]

Yield unique elements from the iterable, src, based on key, in the order in which they first appeared in src.

>>> repetitious = [1, 2, 3] * 10
>>> list(unique_iter(repetitious))
[1, 2, 3]

By default, key is the object itself, but key can either be a callable or, for convenience, a string name of the attribute on which to uniqueify objects, falling back on identity when the attribute is not present.

>>> pleasantries = ['hi', 'hello', 'ok', 'bye', 'yes']
>>> list(unique_iter(pleasantries, key=lambda x: len(x)))
['hi', 'hello', 'bye']