aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/mergedeep/README.md
blob: 86322730cd987e8d78b34b8f4da77e230fb745e6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# [mergedeep](https://mergedeep.readthedocs.io/en/latest/)

[![PyPi release](https://img.shields.io/pypi/v/mergedeep.svg)](https://pypi.org/project/mergedeep/)
[![PyPi versions](https://img.shields.io/pypi/pyversions/mergedeep.svg)](https://pypi.org/project/mergedeep/)
[![Downloads](https://pepy.tech/badge/mergedeep)](https://pepy.tech/project/mergedeep)
[![Conda Version](https://img.shields.io/conda/vn/conda-forge/mergedeep.svg)](https://anaconda.org/conda-forge/mergedeep)
[![Conda Downloads](https://img.shields.io/conda/dn/conda-forge/mergedeep.svg)](https://anaconda.org/conda-forge/mergedeep)
[![Documentation Status](https://readthedocs.org/projects/mergedeep/badge/?version=latest)](https://mergedeep.readthedocs.io/en/latest/?badge=latest)

A deep merge function for 🐍.

[Check out the mergedeep docs](https://mergedeep.readthedocs.io/en/latest/)

## Installation

```bash
$ pip install mergedeep
```

## Usage

```text
merge(destination: MutableMapping, *sources: Mapping, strategy: Strategy = Strategy.REPLACE) -> MutableMapping
```

Deep merge without mutating the source dicts.

```python3
from mergedeep import merge

a = {"keyA": 1}
b = {"keyB": {"sub1": 10}}
c = {"keyB": {"sub2": 20}}

merged = merge({}, a, b, c) 

print(merged)
# {"keyA": 1, "keyB": {"sub1": 10, "sub2": 20}}
```

Deep merge into an existing dict.
```python3
from mergedeep import merge

a = {"keyA": 1}
b = {"keyB": {"sub1": 10}}
c = {"keyB": {"sub2": 20}}

merge(a, b, c) 

print(a)
# {"keyA": 1, "keyB": {"sub1": 10, "sub2": 20}}
```

### Merge strategies:

1. Replace (*default*)

> `Strategy.REPLACE`

```python3
# When `destination` and `source` keys are the same, replace the `destination` value with one from `source` (default).

# Note: with multiple sources, the `last` (i.e. rightmost) source value will be what appears in the merged result. 

from mergedeep import merge, Strategy

dst = {"key": [1, 2]}
src = {"key": [3, 4]}

merge(dst, src, strategy=Strategy.REPLACE) 
# same as: merge(dst, src)

print(dst)
# {"key": [3, 4]}
```

2. Additive

> `Strategy.ADDITIVE`

```python3
# When `destination` and `source` values are both the same additive collection type, extend `destination` by adding values from `source`.
# Additive collection types include: `list`, `tuple`, `set`, and `Counter`

# Note: if the values are not additive collections of the same type, then fallback to a `REPLACE` merge.

from mergedeep import merge, Strategy

dst = {"key": [1, 2], "count": Counter({"a": 1, "b": 1})}
src = {"key": [3, 4], "count": Counter({"a": 1, "c": 1})}

merge(dst, src, strategy=Strategy.ADDITIVE) 

print(dst)
# {"key": [1, 2, 3, 4], "count": Counter({"a": 2, "b": 1, "c": 1})}
```

3. Typesafe replace

> `Strategy.TYPESAFE_REPLACE` or `Strategy.TYPESAFE`

```python3
# When `destination` and `source` values are of different types, raise `TypeError`. Otherwise, perform a `REPLACE` merge.

from mergedeep import merge, Strategy

dst = {"key": [1, 2]}
src = {"key": {3, 4}}

merge(dst, src, strategy=Strategy.TYPESAFE_REPLACE) # same as: `Strategy.TYPESAFE`  
# TypeError: destination type: <class 'list'> differs from source type: <class 'set'> for key: "key"
```

4. Typesafe additive

> `Strategy.TYPESAFE_ADDITIVE`

```python3
# When `destination` and `source` values are of different types, raise `TypeError`. Otherwise, perform a `ADDITIVE` merge.

from mergedeep import merge, Strategy

dst = {"key": [1, 2]}
src = {"key": {3, 4}}

merge(dst, src, strategy=Strategy.TYPESAFE_ADDITIVE) 
# TypeError: destination type: <class 'list'> differs from source type: <class 'set'> for key: "key"
```

## License

MIT &copy; [**Travis Clarke**](https://blog.travismclarke.com/)