grow food, not lawn.

Update lookup_api.py

Russell Ballestrini requested to merge github/fork/Salfiii/patch-1 into master

Created by: Salfiii

makes it possible to provide a list of values to nested_update which is handy if a node exists multiple times in the document but should not get overwritten with the same value. Works best in combination if you use nested_lookup() before, modify the results you get and pass those to nested update. Example:

import copy
from six import iteritems
from nested_lookup import nested_lookup

doc = {
    "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": []
        }
    ]
}

def nested_update(document, key, value, in_place=False):
    """
    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: Key to update the value
    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 type(value) == list:
        val_len = len(value)
    else: 
        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, value, val_len, run = 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, val_len = val_len, run = run)
    elif isinstance(document, dict):
        if document.get(key):
            # check if a value with the coresponding index exists and use it otherwise recycle the intially given value
            val = value[run] if run < val_len  else value[0]
            document[key] = val
            run = run + 1
        for dict_key, dict_value in iteritems(document):
            _nested_update(document=dict_value, key=key, value=value, val_len = val_len, run = run)
    return document

# get all instances of the given element
findings = nested_lookup("plz", doc, False,True)
# alter those instances
updated_findins = list()
for key, val in findings.items():
    for elem in val:
        updated_findins.append(elem + 300)
# update those instances with the altered results
print("**************************** LIST ARG ****************************")
print(nested_update(doc,"plz",updated_findins))
print("**************************** SCALAR ARG ****************************")
# now a regular use with just one argument to test the backwards portability
print(nested_update(doc,"plz", "12345"))

Merge request reports