def get_path(root, path, default=_UNSET):
    """Retrieve a value from a nested object via a tuple representing the
    lookup path.

    >>> root = {'a': {'b': {'c': [[1], [2], [3]]}}}
    >>> get_path(root, ('a', 'b', 'c', 2, 0))
    3

    The path format is intentionally consistent with that of
    :func:`remap`.

    One of get_path's chief aims is improved error messaging. EAFP is
    great, but the error messages are not.

    For instance, ``root['a']['b']['c'][2][1]`` gives back
    ``IndexError: list index out of range``

    What went out of range where? get_path currently raises
    ``PathAccessError: could not access 2 from path ('a', 'b', 'c', 2,
    1), got error: IndexError('list index out of range',)``, a
    subclass of IndexError and KeyError.

    You can also pass a default that covers the entire operation,
    should the lookup fail at any level.

    Args:
       root: The target nesting of dictionaries, lists, or other
          objects supporting ``__getitem__``.
       path (tuple): A list of strings and integers to be successively
          looked up within *root*.
       default: The value to be returned should any
          ``PathAccessError`` exceptions be raised.
    """
    if isinstance(path, basestring):
        path = path.split('.')
    cur = root
    try:
        for seg in path:
            try:
                cur = cur[seg]
            except (KeyError, IndexError) as exc:
                raise PathAccessError(exc, seg, path)
            except TypeError as exc:
                # either string index in a list, or a parent that
                # doesn't support indexing
                try:
                    seg = int(seg)
                    cur = cur[seg]
                except (ValueError, KeyError, IndexError, TypeError):
                    if not is_iterable(cur):
                        exc = TypeError('%r object is not indexable'
                                        % type(cur).__name__)
                    raise PathAccessError(exc, seg, path)
    except PathAccessError:
        if default is _UNSET:
            raise
        return default
    return cur
def get_path ( root , path , default = _UNSET ) : if isinstance ( path , basestring ) : path = path . split ( '.' ) cur = root try : for seg in path : try : cur = cur [ seg ] except ( KeyError , IndexError ) as exc : raise PathAccessError ( exc , seg , path ) except TypeError as exc : try : seg = int ( seg ) cur = cur [ seg ] except ( ValueError , KeyError , IndexError , TypeError ) : if not is_iterable ( cur ) : exc = TypeError ( '%r object is not indexable' % type ( cur ) . __name__ ) raise PathAccessError ( exc , seg , path ) except PathAccessError : if default is _UNSET : raise return default return cur
Retrieve a value from a nested object via a tuple representing the
    lookup path.

    >>> root = {'a': {'b': {'c': [[1], [2], [3]]}}}
    >>> get_path(root, ('a', 'b', 'c', 2, 0))
    3

    The path format is intentionally consistent with that of
    :func:`remap`.

    One of get_path's chief aims is improved error messaging. EAFP is
    great, but the error messages are not.

    For instance, ``root['a']['b']['c'][2][1]`` gives back
    ``IndexError: list index out of range``

    What went out of range where? get_path currently raises
    ``PathAccessError: could not access 2 from path ('a', 'b', 'c', 2,
    1), got error: IndexError('list index out of range',)``, a
    subclass of IndexError and KeyError.

    You can also pass a default that covers the entire operation,
    should the lookup fail at any level.

    Args:
       root: The target nesting of dictionaries, lists, or other
          objects supporting ``__getitem__``.
       path (tuple): A list of strings and integers to be successively
          looked up within *root*.
       default: The value to be returned should any
          ``PathAccessError`` exceptions be raised.