from typing import Union
from typing import Mapping
from typing import Sequence


def recursive_getitem(obj: Union[Mapping, Sequence], *, keys: Sequence):
    """Go along the sequence of ``keys`` through ``obj`` and return the target
    item.

    Args:
        obj (Union[Mapping, Sequence]): The object to get the item from
        keys (Sequence): The sequence of keys to follow

    Returns:
        The target item from ``obj``, specified by ``keys``

    Raises:
        IndexError: If any index in the key sequence was not available
        KeyError: If any key in the key sequence was not available
    """
    # Define some error format strings
    keyerr_fstr = "No such key '{}' of key sequence {} is available in {}."
    idxerr_fstr = "No such index '{}' of key sequence {} is available in {}."

    if len(keys) > 1:
        # Check and continue recursion
        try:
            return recursive_getitem(obj[keys[0]], keys=keys[1:])
        except KeyError as err:
            raise KeyError(keyerr_fstr.format(keys[0], keys, obj)) from err
        except IndexError as err:
            raise IndexError(idxerr_fstr.format(keys[0], keys, obj)) from err
    else:
        # reached the end of the recursion
        try:
            return obj[keys[0]]
        except KeyError as err:
            raise KeyError(keyerr_fstr.format(keys[0], keys, obj)) from err
        except IndexError as err:
            raise IndexError(idxerr_fstr.format(keys[0], keys, obj)) from err