Skip to content

Commit f1b14e8

Browse files
committed
Allow for filling an array when using force to extend with a known value.
1 parent 69adaf1 commit f1b14e8

File tree

3 files changed

+55
-1
lines changed

3 files changed

+55
-1
lines changed

deepdiff/delta.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import copy
22
import logging
3-
from typing import List, Dict, IO, Callable, Set, Union, Optional
3+
from typing import List, Dict, IO, Callable, Set, Union, Optional, Any
44
from functools import partial, cmp_to_key
55
from collections.abc import Mapping
66
from copy import deepcopy
@@ -86,6 +86,7 @@ def __init__(
8686
always_include_values: bool=False,
8787
iterable_compare_func_was_used: Optional[bool]=None,
8888
force: bool=False,
89+
fill: Any=not_found,
8990
):
9091
# for pickle deserializer:
9192
if hasattr(deserializer, '__code__') and 'safe_to_import' in set(deserializer.__code__.co_varnames):
@@ -158,6 +159,7 @@ def _deserializer(obj, safe_to_import=None):
158159
self.serializer = serializer
159160
self.deserializer = deserializer
160161
self.force = force
162+
self.fill = fill
161163
if force:
162164
self.get_nested_obj = _get_nested_obj_and_force
163165
else:
@@ -286,6 +288,13 @@ def _simple_set_elem_value(self, obj, path_for_err_reporting, elem=None, value=N
286288
except IndexError:
287289
if elem == len(obj):
288290
obj.append(value)
291+
elif self.fill is not not_found and elem > len(obj):
292+
while len(obj) < elem:
293+
if callable(self.fill):
294+
obj.append(self.fill(obj, value, path_for_err_reporting))
295+
else:
296+
obj.append(self.fill)
297+
obj.append(value)
289298
else:
290299
self._raise_or_log(ELEM_NOT_FOUND_TO_ADD_MSG.format(elem, path_for_err_reporting))
291300
elif action == GETATTR:

docs/delta.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ force : Boolean, default=False
6868
always_include_values : Boolean, default=False
6969
:ref:`always_include_values_label` is used to make sure the delta objects includes the values that were changed. Sometime Delta tries to be efficient not include the values when it can get away with it. By setting this parameter to True, you ensure that the Delta object will include the values.
7070

71+
fill : Any, default=No Fill
72+
:ref:`delta_fill` This is only relevant if `force` is set. This parameter only applies when force is set and trying to fill an existing array. If the index of the array being applied is larger than the length of the array this value will be used to fill empty spaces of the array to extend it in order to add the new value. If this parameter is not set, the items will get dropped and the array not extended.
73+
7174

7275
**Returns**
7376

tests/test_delta.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2131,6 +2131,48 @@ def test_delta_force1(self):
21312131
expected = {'x': {'y': {3: 4}}, 'q': {'t': 0.5}}
21322132
assert expected == result
21332133

2134+
def test_delta_force_fill(self):
2135+
t1 = {
2136+
'x': {
2137+
'y': [{"b": "c"}, {"b": "c"}, {"b": "c"}, {"b": "c"}]
2138+
},
2139+
'q': {
2140+
'r': 'abc',
2141+
}
2142+
}
2143+
2144+
t2 = {
2145+
'x': {
2146+
'y': [{"b": "c"}, {"b": "c"}, {"b": "c"}, {"b": "c"}, {"b": "c"}, {"b": "c"}, {"b": "c"}]
2147+
},
2148+
'q': {
2149+
'r': 'abc',
2150+
't': 0.5,
2151+
}
2152+
}
2153+
2154+
diff = DeepDiff(t1, t2)
2155+
2156+
delta = Delta(diff=diff, force=True)
2157+
result = {"x": {"y": [1,]}} + delta
2158+
expected = {'x': {'y': [1]}, 'q': {'t': 0.5}}
2159+
assert expected == result
2160+
2161+
2162+
delta = Delta(diff=diff, force=True, fill=None)
2163+
result = {"x": {"y": [1,]}} + delta
2164+
expected = {'x': {'y': [1, None, None, None, {"b": "c"}, {"b": "c"}, {"b": "c"}]}, 'q': {'t': 0.5}}
2165+
assert expected == result
2166+
2167+
2168+
def fill_func(obj, value, path):
2169+
return value.copy()
2170+
2171+
delta = Delta(diff=diff, force=True, fill=fill_func)
2172+
result = {"x": {"y": [1,]}} + delta
2173+
expected = {'x': {'y': [1, {"b": "c"}, {"b": "c"}, {"b": "c"}, {"b": "c"}, {"b": "c"}, {"b": "c"}]}, 'q': {'t': 0.5}}
2174+
assert expected == result
2175+
21342176
def test_flatten_dict_with_one_key_added(self):
21352177
t1 = {"field1": {"joe": "Joe"}}
21362178
t2 = {"field1": {"joe": "Joe Nobody"}, "field2": {"jimmy": "Jimmy"}}

0 commit comments

Comments
 (0)