from functools import reduce


def deepgetattr(obj, attr, default=AttributeError):
    """
    Recurses through an attribute chain to get the ultimate value (obj/data/member/value)
    from: http://pingfive.typepad.com/blog/2010/04/deep-getattr-python-function.html

    >>> class Universe(object):
    ...     def __init__(self, galaxy):
    ...             self.galaxy = galaxy
    ...

    >>> class Galaxy(object):
    ...     def __init__(self, solarsystem):
    ...             self.solarsystem = solarsystem
    ...

    >>> class SolarSystem(object):
    ...     def __init__(self, planet):
    ...             self.planet = planet
    ...

    >>> class Planet(object):
    ...     def __init__(self, name):
    ...             self.name = name
    ...

    >>> universe = Universe(Galaxy(SolarSystem(Planet('Earth'))))
    >>> deepgetattr(universe, 'galaxy.solarsystem.planet.name')
    'Earth'
    >>> deepgetattr(universe, 'solarsystem.planet.name', default=TypeError)
    <class 'TypeError'>
    """
    try:
        return reduce(getattr, attr.split("."), obj)
    except AttributeError:
        if default is not AttributeError:
            return default
        raise