"nested_alter" and update of "nested_update" (#16)

* Update lookup_api.py

moved the typecheck of the value argument to the wrapper function.

* added tests for nested_update Test

* pep8 format standards
moded _call_callback out of the nested_alter Method
Raised an Exception is no list is provided but treas_as_elemenet is false
treat_list_as_element:bool renamed to treat_as_element:bool and set default to True

* Auto commit via script

* Create CONTRIBUTORS.rst

* Rename CONTRIBUTORS.rst to CONTRIBUTING.rst

* Update CONTRIBUTING.rst

* Fix for issue #17 (#18)

* Fix for issue #17
* Updating version (and) Adding Travis CI support
* Adding Build status to README

* changed the type annotation of the input document (removed it)
removed the output type hint
change the Readme

* Update lookup_api.py

moved the typecheck of the value argument to the wrapper function.

* added tests for nested_update Test

* pep8 format standards
moded _call_callback out of the nested_alter Method
Raised an Exception is no list is provided but treas_as_elemenet is false
treat_list_as_element:bool renamed to treat_as_element:bool and set default to True


* changed the type annotation of the input document (removed it)
removed the output type hint
change the Readme
This commit is contained in:
Salfiii 2019-04-30 02:06:10 +02:00 committed by Russell Ballestrini
parent 0e8723b822
commit 4f37d265c8
5 changed files with 670 additions and 91 deletions

4
.gitignore vendored
View file

@ -5,4 +5,6 @@ __pycache__*
build/*
dist/*
nested_lookup.egg-info/*
.cache/
.cache
.vscode
git_commit.sh

View file

@ -24,6 +24,11 @@ A document in this case is a a mixture of Python dictionary and list objects typ
Given a document, find all occurrences of the given key and delete it.
By default, returns a copy of the document.
To mutate the original specify the `in_place=True` argument.
*nested_alter:*
Given a document, find all occurrences of the given key and alter it with a callback function
By default, returns a copy of the document.
To mutate the original specify the `in_place=True` argument.
*get_all_keys:*
Fetch all keys from a deeply nested dictionary.
@ -75,6 +80,31 @@ quick tutorial
>>> nested_delete(document, 'taco')
[{}, {'salsa': [{'burrito': {}}]}]
*Nested Alter*:
write a callback function which processes a scalar value.
Be aware about the possible types which can be passed to the callback functions.
In this example we can be sure that only int will be passed, in production you should check the type because it could be anything.
.. code-block:: python
>>> def callback(data):
>>> return data + 10 # add 10 to every taco prize
The alter-version only works for scalar input (one dict), if you need to adress a list of dicts, you have to
manually iterate over those and pass them to nested_update one by one
.. code-block:: python
>>> out =[]
>>> for elem in document:
>>> altered_document = nested_alter(elem,"taco", callback)
>>> out.append(altered_document)
>>> print(out)
[ { 'taco' : 52 } , { 'salsa' : [ { 'burrito' : { 'taco' : 79 } } ] } ]
>>> from nested_lookup import get_all_keys
>>> get_all_keys(document)
@ -210,8 +240,10 @@ misc
* Russell Ballestrini
* Douglas Miranda
* Ramesh RV
* Salfiii (Florian S.)
:web:
* http://russell.ballestrini.net
* http://douglasmiranda.com
* https://gist.github.com/douglasmiranda/5127251
* https://github.com/Salfiii

View file

@ -1,3 +1,3 @@
from .nested_lookup import nested_lookup, get_all_keys, get_occurrence_of_key,\
get_occurrence_of_value
from .lookup_api import nested_update, nested_delete
from .lookup_api import nested_update, nested_delete, nested_alter

View file

@ -1,14 +1,16 @@
import copy
import warnings
from six import iteritems
from nested_lookup import nested_lookup
def nested_delete(document, key, in_place=False):
def nested_delete(document, key: str, in_place: bool = False):
if not in_place:
document = copy.deepcopy(document)
return _nested_delete(document=document, key=key)
def _nested_delete(document, key):
def _nested_delete(document, key: str) -> dict:
"""
Method to delete a key->value pair from a nested document
Args:
@ -22,35 +24,187 @@ def _nested_delete(document, key):
for list_items in document:
_nested_delete(document=list_items, key=key)
elif isinstance(document, dict):
if document.get(key) is not None:
if document.get(key):
del document[key]
for dict_key, dict_value in iteritems(document):
_nested_delete(document=dict_value, key=key)
return document
def nested_update(document, key, value, in_place=False):
if not in_place:
document = copy.deepcopy(document)
return _nested_update(document=document, key=key, value=value)
def _nested_update(document, key, value):
def nested_update(document, key: str, value: object,
in_place: bool = False,
treat_as_element: bool = True):
"""
Method to update a key->value pair in a nested document
Args:
document: Might be List of Dicts (or) Dict of Lists (or)
Dict of List of Dicts etc...
Dict of List of Dicts etc...
key: Key to update the value
value: Value to set
in_place (bool):
True: modify the dict in place;
False: create a deep copy of the dict and modify it
Defaults to False
treat_list_element (bool):
True: if a list is provided as "value", the function trys
to match the list elements to the occurences of the key.
If the key occures more often than the provided list has
elements, the first element gets recycled.
False: the provided list is treated as one scalar value and
will be set as value to every key that matches.
Defaults to True (because of backwards portability of the package).
Return:
Returns a document that has updated key, value pair.
"""
# check if a list or scalar value is provided and create a list
# from the scalar value
# check the length of the list and provide it to _nested_update
if not treat_as_element and not isinstance(value, list):
raise Exception('You need to pass value as list if you opt for' +
'this feature')
elif treat_as_element:
value = [value]
val_len = len(value)
if not in_place:
document = copy.deepcopy(document)
return _nested_update(document=document, key=key, value=value,
val_len=val_len)
def _nested_update(document, key: str, value: object,
val_len: int, run: int = 0):
"""
Method to update a key->value pair in a nested document
Args:
document: Might be List of Dicts (or) Dict of Lists (or)
Dict of List of Dicts etc...
key (str): Key to update the value
value (list): value(s) which should be used for replacement purpouse
val_len (int): lenght of the value element
run (int): holds the number of findings for the given key.
Every time the key is found, run = run + 1. If the list value[run]
exists,
the corresponding element is used for replacement purpouse.
Defaults to 0.
Return:
Returns a document that has updated key, value pair.
"""
if isinstance(document, list):
for list_items in document:
_nested_update(document=list_items, key=key, value=value)
_nested_update(document=list_items, key=key, value=value,
val_len=val_len, run=run)
elif isinstance(document, dict):
if document.get(key) is not None:
document[key] = value
if document.get(key):
# check if a value with the coresponding index exists and
# use it otherwise recycle the intially given value
if run < val_len:
val = value[run]
else:
run = 0
val = value[run]
document[key] = val
run = run + 1
for dict_key, dict_value in iteritems(document):
_nested_update(document=dict_value, key=key, value=value)
_nested_update(document=dict_value, key=key, value=value,
val_len=val_len, run=run)
return document
def nested_alter(document, key: str, callback_function=None,
function_parameters: list = None, conversion_function=None,
wild_alter: bool = False, in_place: bool = True):
"""
Method to alter all values of the occurences of the key "key".
The provided callback_function is used to alter the scalar values
Args:
document: Might be List of Dicts (or) Dict of Lists (or)
Dict of List of Dicts etc...
key: Key to update the value
callback_function :A callback function which alters a scalar value
HINT: You should be aware that not every element might be of
the same type, please check this in your function!
function_parameters (list):
If the callback_function has additional input arguments except
the scalar value, please specify those in this list.
conversion_function: A conversion function like str() which should be
applied to every found value before it is passed to the
"callback_function"
wild_alter: Find matching elements via wild-match by the given keys
and alter those.
HINT: Keep in mind that the wild-match might return unexpected types!
in_place (bool):
True: modify the dict in place;
False: create a deep copy of the dict and modify it
Defaults to False
Return:
Returns a document that has updated key, value pair.
"""
# check if a list or scalar value is provided and create a list from
# the scalar value
# check the length of the list and provide it to _nested_update
if isinstance(key, list):
key_len = len(key)
else:
key = [key]
key_len = len(key)
if not in_place:
document = copy.deepcopy(document)
return _nested_alter(document=document, keys=key,
callback_function=callback_function,
function_parameters=function_parameters,
conversion_function=conversion_function,
wild_alter=wild_alter,
in_place=in_place, key_len=key_len)
def _call_callback(value_list: list, callback_function,
function_parameters: list, conversion_function):
"""
internal helper to call the callback function
"""
return_list = []
# loop over all values
for value in value_list:
# apply the conversion function
if conversion_function is not None:
value = conversion_function(value)
# if functions arguments are present, expand the list to variables
# via the magic operator *
if function_parameters:
trans_val = callback_function(value, *function_parameters)
else:
trans_val = callback_function(value)
# append the transformed element to the list
return_list.append(trans_val)
return return_list
def _nested_alter(document, keys, callback_function,
function_parameters: list, conversion_function,
wild_alter: bool, in_place: bool, key_len: int):
"""
"""
# return data if no callback_function is provided
if callback_function is None:
warnings.warn("Please provide a callback_function to nested_alter().")
return document
# iterate over all given keys in the list
for key in keys:
# try to find the key:
findings = nested_lookup(key, document, with_keys=True, wild=wild_alter)
for k, v in findings.items():
trans_val = _call_callback(v, callback_function,
function_parameters,
conversion_function)
# use the transformed value and apply the update to the key
# (dont treat the lists as elements here)
document = nested_update(document, k, trans_val,
in_place=in_place,
treat_as_element=False)
return document

View file

@ -1,6 +1,7 @@
from unittest import TestCase
from nested_lookup import nested_update, nested_delete
from nested_lookup import nested_lookup, nested_update
from nested_lookup import nested_delete, nested_alter
class BaseLookUpApi(TestCase):
@ -56,11 +57,51 @@ class BaseLookUpApi(TestCase):
}
self.sample_data4 = {
"hardware_details": {
"model_name": 'MacBook Pro',
"total_number_of_cores": 0,
"memory": False
}
"modelversion": "1.1.0",
"vorgangsID": "1",
"versorgungsvorschlagDatum": 1510558834978,
"eingangsdatum": 1510558834978,
"plz": 82269,
"vertragsteile": [
{
"typ": "1",
"beitragsDaten": {
"endalter": 85,
"brutto": 58.76,
"netto": 58.76,
"zahlungsrhythmus": "MONATLICH",
"plz": 86899
},
"beginn": 1512082800000,
"lebenslang": "True",
"ueberschussverwendung": {
"ueberschussverwendung": "2",
"indexoption": "3"
},
"deckung": [
{
"typ": "2",
"art": "1",
"leistung": {
"value": 7500242424.0,
"einheit": "2"
},
"leistungsRhythmus": "1"
}
],
"zuschlagNachlass": []
},
{
"typ": "1",
"beitragsDaten": {
"endalter": 85,
"brutto": 0.6,
"netto": 0.6,
"zahlungsrhythmus": "1"
},
"zuschlagNachlass": []
}
]
}
@ -95,52 +136,9 @@ class TestNestedDelete(BaseLookUpApi):
result, nested_delete(self.sample_data3, 'monitoring_zones')
)
def test_sample_data4(self):
result1 = {
"hardware_details": {
"model_name": 'MacBook Pro',
"memory": False
}
}
self.assertEqual(
result1, nested_delete(self.sample_data4, 'total_number_of_cores')
)
result2 = {
"hardware_details": {
"model_name": 'MacBook Pro',
"total_number_of_cores": 0
}
}
self.assertEqual(
result2, nested_delete(self.sample_data4, 'memory')
)
def test_nested_delete_in_place_false(self):
"""
nested_delete with in_place argument set to 'False'
should mutate and return a copy of the original document
"""
before_id = id(self.sample_data1)
result = nested_delete(
self.sample_data1, 'build_version', in_place=False)
after_id = id(result)
# the object ids should _not_ match.
self.assertNotEqual(before_id, after_id)
def test_nested_delete_in_place_true(self):
"""
nested_delete with in_place argument set to 'True'
should mutate and return the original document
"""
before_id = id(self.sample_data1)
result = nested_delete(
self.sample_data1, 'build_version', in_place=True)
after_id = id(result)
# the object ids should match.
self.assertEqual(before_id, after_id)
class TestNestedUpdate(BaseLookUpApi):
def test_sample_data1(self):
result = {
"build_version": "Test1",
@ -155,22 +153,39 @@ class TestNestedUpdate(BaseLookUpApi):
result, nested_update(self.sample_data1, 'build_version', 'Test1')
)
def test_sample_data1_list_input_treat_list_as_element_true(self):
result = {
"build_version": ["Test5", "Test6", "Test7"],
"os_details": {
"product_version": '10.13.6',
"build_version": ["Test5", "Test6", "Test7"]
},
"name": 'Test',
"date": 'YYYY-MM-DD HH:MM:SS'
}
self.assertEqual(
result, nested_update(
self.sample_data1,
'build_version',
["Test5", "Test6", "Test7"],
treat_as_element=True)
)
def test_nested_update_in_place_false(self):
"""
nested_update with in_place argument set to 'False'
should mutate and return a copy of the original document
ested_update should mutate and return a copy of the original document
"""
before_id = id(self.sample_data1)
result = nested_update(
self.sample_data1, 'build_version', 'Test2', in_place=False)
result = nested_update(self.sample_data1, 'build_version', 'Test2',
in_place=False)
after_id = id(result)
# the object ids should _not_ match.
self.assertNotEqual(before_id, after_id)
def test_nested_update_in_place_true(self):
"""
nested_update with in_place argument set to 'True'
should mutate and return the original document
nested_update should mutate and return the original document
"""
before_id = id(self.sample_data1)
result = nested_update(
@ -179,6 +194,146 @@ class TestNestedUpdate(BaseLookUpApi):
# the object ids should match.
self.assertEqual(before_id, after_id)
def test_nested_update_in_place_true_list_input(self):
doc = self.sample_data4
# get all instances of the given element
findings = nested_lookup("plz", doc, False, True)
# alter those instances
updated_findings = list()
for key, val in findings.items():
for elem in val:
updated_findings.append(elem + 300)
# update those instances with the altered results
doc_updated = nested_update(
doc, "plz", updated_findings, treat_as_element=False)
elem1 = doc_updated["plz"] # 85269
# 87199
elem2 = doc_updated["vertragsteile"][0]["beitragsDaten"]["plz"]
self.assertEqual(elem1, 82569)
self.assertEqual(elem2, 87199)
def test_nested_update_in_place_false_list_input(self):
doc = self.sample_data4
# get all instances of the given element
findings = nested_lookup("plz", doc, False, True)
# alter those instances
updated_findings = list()
for key, val in findings.items():
for elem in val:
updated_findings.append(elem + 300)
# update those instances with the altered results
doc_updated = nested_update(
doc, "plz", updated_findings, in_place=False,
treat_as_element=False)
elem1 = doc_updated["plz"]
elem2 = doc_updated["vertragsteile"][0]["beitragsDaten"]["plz"]
self.assertEqual(elem1, 82569)
self.assertEqual(elem2, 87199)
def test_nested_update_in_place_false_list_input_as_element_false(self):
doc = self.sample_data4
# get all instances of the given element
list_input = [1, 2, 3, 4, 5]
# update those instances with the altered results
doc_updated = nested_update(
doc, "plz", list_input, in_place=False, treat_as_element=False)
elem1 = doc_updated["plz"]
elem2 = doc_updated["vertragsteile"][0]["beitragsDaten"]["plz"]
# should not work without specifying "treat_list_as_element = True"
# in nested_update
self.assertNotEqual(elem1, list_input)
self.assertNotEqual(elem2, list_input)
def test_nested_update_in_place_false_list_input_as_element_true(self):
doc = self.sample_data4
# get all instances of the given element
list_input = [1, 2, 3, 4, 5]
# update those instances with the altered results
doc_updated = nested_update(
doc, "plz", list_input, in_place=False, treat_as_element=True)
elem1 = doc_updated["plz"]
elem2 = doc_updated["vertragsteile"][0]["beitragsDaten"]["plz"]
# should not work without specifying "treat_list_as_element = True"
# in nested_update
self.assertEqual(elem1, list_input)
self.assertEqual(elem2, list_input)
def test_nested_update_in_place_true_list_input_as_element_false(self):
doc = self.sample_data4
# get all instances of the given element
list_input = [1, 2, 3, 4, 5]
# update those instances with the altered results
doc_updated = nested_update(
doc, "plz", list_input, in_place=True, treat_as_element=False)
elem1 = doc_updated["plz"]
elem2 = doc_updated["vertragsteile"][0]["beitragsDaten"]["plz"]
# should not work without specifying "treat_list_as_element = True"
# in nested_update
self.assertNotEqual(elem1, list_input)
self.assertNotEqual(elem2, list_input)
def test_nested_update_in_place_true_list_input_as_element_true(self):
doc = self.sample_data4
# get all instances of the given element
list_input = [1, 2, 3, 4, 5]
# update those instances with the altered results
doc_updated = nested_update(
doc, "plz", list_input, in_place=True, treat_as_element=True)
elem1 = doc_updated["plz"]
elem2 = doc_updated["vertragsteile"][0]["beitragsDaten"]["plz"]
# should not work without specifying "treat_list_as_element = True"
# in nested_update
self.assertEqual(elem1, list_input)
self.assertEqual(elem2, list_input)
def test_nested_delete_in_place_false(self):
"""
nested_delete should mutate and return a copy of the original document
"""
before_id = id(self.sample_data1)
result = nested_delete(
self.sample_data1, 'build_version', in_place=False)
after_id = id(result)
# the object ids should _not_ match.
self.assertNotEqual(before_id, after_id)
def test_nested_delete_in_place_true(self):
"""nested_delete should mutate and return the original document"""
before_id = id(self.sample_data1)
result = nested_delete(
self.sample_data1, 'build_version', in_place=True)
after_id = id(result)
# the object ids should match.
self.assertEqual(before_id, after_id)
def test_nested_update_taco_for_example(self):
document = [
{'taco': 42},
{'salsa': [{'burrito': {'taco': 69}}]}
]
updated_document = nested_update(
document, "taco", [100, 200], treat_as_element=False)
self.assertEqual(updated_document[0]["taco"], 100)
# The multi-update version only works for scalar input,
# if you need to adress a list of dicts, you have to
# manually iterate over those and pass them to nested_update
# one by one
self.assertNotEqual(
updated_document[1]["salsa"][0]["burrito"]["taco"], 200)
def test_nested_update_raise_error(self):
doc = self.sample_data4
# get all instances of the given element
list_input = 1
# update those instances with the altered results
self.assertRaises(
Exception,
nested_update, doc, "plz", list_input,
in_place=True, treat_as_element=False
)
def test_sample_data2(self):
result = {
"hardware_details": {
@ -217,28 +372,264 @@ class TestNestedUpdate(BaseLookUpApi):
)
def test_sample_data4(self):
result1 = {
"hardware_details": {
"model_name": 'MacBook Pro',
"total_number_of_cores": 1,
"memory": False
}
result = {
"modelversion": {
'key1': ['value1'],
'key2': 'value2'
},
"vorgangsID": "1",
"versorgungsvorschlagDatum": 1510558834978,
"eingangsdatum": 1510558834978,
"plz": 82269,
"vertragsteile": [
{
"typ": "1",
"beitragsDaten": {
"endalter": 85,
"brutto": 58.76,
"netto": 58.76,
"zahlungsrhythmus": "MONATLICH",
"plz": 86899
},
"beginn": 1512082800000,
"lebenslang": "True",
"ueberschussverwendung": {
"ueberschussverwendung": "2",
"indexoption": "3"
},
"deckung": [
{
"typ": "2",
"art": "1",
"leistung": {
"value": 7500242424.0,
"einheit": "2"
},
"leistungsRhythmus": "1"
}
],
"zuschlagNachlass": []
},
{
"typ": "1",
"beitragsDaten": {
"endalter": 85,
"brutto": 0.6,
"netto": 0.6,
"zahlungsrhythmus": "1"
},
"zuschlagNachlass": []
}
]
}
self.assertEqual(
result1, nested_update(
self.sample_data4, key='total_number_of_cores',
value=1
result, nested_update(
self.sample_data4, 'modelversion',
{
'key1': ['value1'],
'key2': 'value2'
}
)
)
result2 = {
"hardware_details": {
"model_name": 'MacBook Pro',
"total_number_of_cores": 0,
"memory": True
}
class TestNestedAlter(BaseLookUpApi):
def test_nested_alter_in_place_true(self):
# callback functions
def callback(data):
return str(data) + "###"
doc_updated = nested_alter(
self.sample_data4, "vorgangsID", callback, in_place=True)
vorgangsid = doc_updated["vorgangsID"]
self.assertEqual(vorgangsid, "1###")
def test_nested_alter_in_place_false(self):
# callback functions
def callback(data):
return str(data) + "###"
doc_updated = nested_alter(
self.sample_data4, "vorgangsID", callback, in_place=False)
vorgangsid = doc_updated["vorgangsID"]
# should not work without specifying
# "treat_list_as_element = True" in nested_update
self.assertEqual(vorgangsid, "1###")
def test_nested_alter_list_input_in_place_true(self):
# callback functions
def callback(data):
return str(data) + "###"
doc_updated = nested_alter(
self.sample_data4, ["plz", "vorgangsID"], callback, in_place=True)
plz1 = doc_updated["plz"]
plz2 = doc_updated["vertragsteile"][0]["beitragsDaten"]["plz"]
vorgangsid = doc_updated["vorgangsID"]
# should not work without specifying
# "treat_list_as_element = True" in nested_update
self.assertEqual(plz1, "82269###")
self.assertEqual(plz2, "86899###")
self.assertEqual(vorgangsid, "1###")
def test_nested_alter_list_input_with_args_in_place_true(self):
# callback functions
def callback(data, str1, str2):
return str(data) + str1 + str2
doc_updated = nested_alter(self.sample_data4, [
"plz", "vorgangsID"],
callback,
function_parameters=["abc", "def"],
in_place=True
)
plz1 = doc_updated["plz"]
plz2 = doc_updated["vertragsteile"][0]["beitragsDaten"]["plz"]
vorgangsid = doc_updated["vorgangsID"]
# should not work without specifying
# "treat_list_as_element = True" in nested_update
self.assertEqual(plz1, "82269abcdef")
self.assertEqual(plz2, "86899abcdef")
self.assertEqual(vorgangsid, "1abcdef")
def test_nested_alter_list_input_with_args_in_place_false(self):
# callback functions
def callback(data, str1, str2):
return str(data) + str1 + str2
doc_updated = nested_alter(self.sample_data4, [
"plz", "vorgangsID"],
callback,
function_parameters=["abc", "def"],
in_place=False
)
plz1 = doc_updated["plz"]
plz2 = doc_updated["vertragsteile"][0]["beitragsDaten"]["plz"]
vorgangsid = doc_updated["vorgangsID"]
# should not work without specifying
# "treat_list_as_element = True" in nested_update
self.assertEqual(plz1, "82269abcdef")
self.assertEqual(plz2, "86899abcdef")
self.assertEqual(vorgangsid, "1abcdef")
def test_nested_alter_list_input_in_place_false(self):
# callback functions
def callback(data):
return str(data) + "###"
doc_updated = nested_alter(
self.sample_data4, ["plz", "vorgangsID"], callback, in_place=False)
plz1 = doc_updated["plz"]
plz2 = doc_updated["vertragsteile"][0]["beitragsDaten"]["plz"]
vorgangsid = doc_updated["vorgangsID"]
# should not work without specifying
# "treat_list_as_element = True" in nested_update
self.assertEqual(plz1, "82269###")
self.assertEqual(plz2, "86899###")
self.assertEqual(vorgangsid, "1###")
def test_nested_alter_taco_for_example(self):
documents = [
{'taco': 42},
{'salsa': [{'burrito': {'taco': 69}}]}
]
# write a callback function which processes a scalar value.
# Be aware about the possible types which can be passed to
# the callback functions.
# In this example we can be sure that only int will be passed,
# in production you should check the type because it could be
# anything.
def callback(data):
return data + 10 # (data/100*10)
# The alter-version only works for scalar input (one dict),
# if you need to adress a list of dicts, you have to
# manually iterate over those and pass them to
# nested_update one by one
out = []
for elem in documents:
altered_document = nested_alter(elem, "taco", callback)
out.append(altered_document)
self.maxDiff = None
self.assertEqual(out[0]["taco"], 52)
self.assertEqual(out[1]["salsa"][0]["burrito"]["taco"], 79)
def test_sample_data4(self):
result = {
"modelversion": "1.1.0",
"vorgangsID": "1",
"versorgungsvorschlagDatum": 1510558834978,
"eingangsdatum": 1510558834978,
"plz": 82270,
"vertragsteile": [
{
"typ": "1",
"beitragsDaten": {
"endalter": 85,
"brutto": 58.76,
"netto": 58.76,
"zahlungsrhythmus": "MONATLICH",
"plz": 86900
},
"beginn": 1512082800000,
"lebenslang": "True",
"ueberschussverwendung": {
"ueberschussverwendung": "2",
"indexoption": "3"
},
"deckung": [
{
"typ": "2",
"art": "1",
"leistung": {
"value": 7500242424.0,
"einheit": "2"
},
"leistungsRhythmus": "1"
}
],
"zuschlagNachlass": []
},
{
"typ": "1",
"beitragsDaten": {
"endalter": 85,
"brutto": 0.6,
"netto": 0.6,
"zahlungsrhythmus": "1"
},
"zuschlagNachlass": []
}
]
}
# add +1 to all plz
def callback(data):
return data + 1
self.maxDiff = None
self.assertEqual(
result2, nested_update(
self.sample_data4, key='memory', value=True
)
result, nested_alter(self.sample_data4, 'plz', callback)
)