Overdub

Load and merge nested configurations. It works with Python 2.7 and any Python 3. Code source is published at https://lab.errorist.xyz/py/overdub.

Installation

python -m pip install overdub

Quick Start

With these structures:

from overdub import MutableOverdub

a = {'foo': 1, 'bar': {'baz': 2}, 'qux': {'one': 1}}
b = {'foo': 3, 'bar': {'baz': 4}, 'qux': {'two': 2}}

Update:

overdubbed = MutableOverdub(a)
overdubbed.update(b)
assert overdubbed.foo == 3
assert overdubbed.bar.baz == 4
assert overdubbed.qux == {'two': 2}

Merge:

overdubbed = MutableOverdub(a)
overdubbed.merge(b)
assert overdubbed.foo == 3
assert overdubbed.bar.baz == 4
assert overdubbed.qux == {'one': 1, 'two': 2}

Rebase:

overdubbed = MutableOverdub(a)
overdubbed.rebase(b)
assert overdubbed.foo == 1
assert overdubbed.bar.baz == 2
assert overdubbed.qux == {'one': 1, 'two': 2}

Unbound the data:

overdubbed = MutableOverdub(a)
assert isinstance(overdubbed, Overdub)
naked = MutableOverdub(a)
assert not isinstance(naked, Overdub)

Freeze configuration:

overdubbed = overdubbed.frozen()

YAML files

It can also read configuration from yaml files, for this install:

python -m pip install overdub[yaml]

And then, merge all files:

from overdub import yaml

overdubbed = yaml.load_from_file('a.yml', b.yml')
assert overdubbed.foo == 3
assert overdubbed.bar.baz == 4
assert overdubbed.qux == {'one': 1, 'two': 2}

API

class overdub.Overdub(data=None)

Access mapping as a layer.

When possible, keys will be accessed as attributes.

For example:

>>> overdub = Overdub({'foo': 1, 'bar': {'baz': 'qux'}})
>>> overdub.foo
1
>>> overdub['foo']
1
class overdub.MutableOverdub(data=None)

An Overdub with mutability abilities.

frozen()

Froze data

>>> a = MutableOverdub()
>>> b = a.frozen()
>>> isinstance(b, Overdub)
>>> not isinstance(b, MutableOverdub)
Returns:
Overdub: the frozen data
merge(data)

Merge data recursively

>>> a = {'foo': {'one': 1}, 'bar': 1}
>>> b = {'foo': {'two': 2}, 'bar': 2}
>>> o = MutableOverdub(a)
>>> o.merge(b)
>>> assert o == {'foo': {'one': 1, 'two': 2}, 'bar': 2}
Parameters:
data (Mapping): data to be merged
rebase(data)

Rebase data

>>> a = {'foo': {'one': 1}, 'bar': 1}
>>> b = {'foo': {'two': 2}, 'bar': 2}
>>> o = MutableOverdub(a)
>>> o.rebase(b)
>>> assert o == {'foo': {'one': 1, 'two': 2}, 'bar': 2}
Parameters:
data (Mapping): data to be rebased
unbound()

unbound the data of Overdub layer

>>> a = MutableOverdub()
>>> b = a.unbound()
>>> not isinstance(b, Overdub)
>>> not isinstance(b, MutableOverdub)
Returns:
Mapping: the data without magic
update(data)

Update data

>>> a = {'foo': 1, 'bar': {'baz': 2}}
>>> b = {'bar': {'baz': 4}, 'qux': {'one': 1}}
>>> o = MutableOverdub(a)
>>> o.update(b)
>>> assert o == {'foo': 1, 'bar': {'baz': 4}, 'qux': {'one': 1}}
Parameters:
data (Mapping): data to be updated