Source code for understreck.nested_get

# -*- coding: utf-8 -*-
from .exceptions import InvalidArgumentError


def _is_list(key):
    return "[" in key


def _strip_position(key):
    return key.split("[")[0]


def _get_positions(key):
    key_without_name = key.split("[")[0]
    positions_string = key.replace(key_without_name, "")
    raw_positions = positions_string.split("]")
    raw_positions = [x for x in raw_positions if x != ""]

    positions = [_position(x) for x in raw_positions]
    return positions


def _position(key):
    position = key.split("[")[-1]
    position = position.split("]")[0]
    return int(position)


[docs]def nested_get(input_dict, nested_key): """Get a subkey from a dict This will return a subkey from a dictionary. It solves a problem when having to perform safe get on nested dictionaries. Arguments: input_dict {dict} -- The dictionary to perform the get on nested_key {str, list, tuple} -- The key can be or dot delimited string or list/tuple. Returns: Object or None -- The value of the key or None """ if not isinstance(nested_key, (str, list, tuple)): raise InvalidArgumentError("The nested_key is not the correct type") if not isinstance(input_dict, dict): raise InvalidArgumentError("The input_dict is not the correct type") normalized_nested_key = None if isinstance(nested_key, str): normalized_nested_key = nested_key.split(".") elif isinstance(nested_key, (list, tuple)): normalized_nested_key = nested_key internal_dict_value = input_dict for k in normalized_nested_key: if _is_list(k): # Handle chained lists positions = _get_positions(k) internal_dict_value = internal_dict_value.get(_strip_position(k), None) for position in positions: try: internal_dict_value = internal_dict_value[position] except IndexError: return None else: internal_dict_value = internal_dict_value.get(k, None) if internal_dict_value is None: return None return internal_dict_value
get = nested_get