from typing import Mapping


def mapping_update(mapping, *args, **kwargs):
    """Deep update a nested mapping data structure.

    Unlike Python's ``dict.update()`` method, if the same key is present in
    both the target and this mapping and the value is a dictionary, it
    will be updated instead of being overwritten.

    .. code-block:: python

        >>> d1 = {'baz': {'foo': 'foo'}, 'fizz': 'buzz'}
        >>> d2 = {'baz': {'bar': 'bar'}, 'fizz': 'fizzbuzz'}
        >>> mapping_update(d1, d2)
        {'baz': {'foo': 'foo', 'bar': 'bar'}, 'fizz': 'fizzbuzz'}


    :param mapping: The mapping data structure to be updated.
    :type mapping: ~collections.abc.Mapping


    :returns: The updating mapping.
    :rtype mapping: ~collections.abc.Mapping

    """
    for k, v in mapping.__class__(*args, **kwargs).items():
        if isinstance(v, Mapping):
            mapping[k] = mapping_update(mapping.get(k, {}), v)
        else:
            mapping[k] = v

    return mapping