from typing import Any
from typing import Union
from typing import Sequence


def getattrpath(value: Any, attrpath: Union[str, Sequence[str]]) -> Any:
    """
    Get a nested named attribute, described by *attrpath*, from the
    object *value*, or return None if one of the attributes in the path
    doesn't exist.

    *attrpath* may be a dotted-string like ``a.b.c`` or a sequence
    (list or tuple) like ``("a", "b", "c")``.

    >>> class Namespace:
    ...     def __init__(self):
    ...         self.__dict__ = {}
    ...     def __repr__(self):
    ...         return repr(self.__dict__)

    >>> obj = Namespace()
    >>> obj.a = Namespace()
    >>> obj.a.b = Namespace()
    >>> obj.a.b.c = 42
    >>> getattrpath(obj, "a")
    {'b': {'c': 42}}
    >>> getattrpath(obj, "a.b.c")
    42
    >>> getattrpath(obj, "a.b.x")
    >>> getattrpath(obj, "a.x")
    >>> getattrpath(obj, "x")
    >>> getattrpath(obj, ("a", "b", "c"))
    42
    """
    if isinstance(attrpath, str):
        attrpath = attrpath.split(".")

    assert len(attrpath) != 0

    for attr in attrpath:
        value = getattr(value, attr, None)

        if value is None:
            return None

    return value