def dotify(adict):
    """
    Contract a dictionary to use "dot notation".

    This support both standard dict or OrderedDict, or any dict subclass.

    For example::

    .. code-block:: python3

        adict = {
            'key1': {
                'key2': {
                    'key3': 'string1',
                    'key4': 1000,
                },
            },
            'key4': {
                'key5': 'string2',
            },
        }

        contracted = dotify(adict)

    Will produce:

    .. code-block:: python3

        {
            'key1.key2.key3': 'string1',
            'key1.key2.key4': 1000,
            'key4.key5': 'string2',
        }

    :param dict adict: Original dictionary.

    :return: The contracted dictionary. Same datatype of the input.
    :rtype: dict
    """
    assert isinstance(adict, dict), 'Invalid dictionary'

    dotdict = type(adict)()

    def _dotify(anode, crumbs):
        if isinstance(anode, dict):
            for key, value in anode.items():
                _dotify(value, crumbs + [key])
            return

        dotdict['.'.join(crumbs)] = anode

    _dotify(adict, [])

    return dotdict