Deserialize any string or stream like object into a Python data structure.

    :param stream_or_string: stream or string to deserialize.
    :param options: options given to lower configparser module.

def deserialize(stream_or_string, **options):
    '''
    Deserialize any string or stream like object into a Python data structure.

    :param stream_or_string: stream or string to deserialize.
    :param options: options given to lower configparser module.
    '''

    if six.PY3:
        cp = configparser.ConfigParser(**options)
    else:
        cp = configparser.SafeConfigParser(**options)

    try:
        if not isinstance(stream_or_string, (bytes, six.string_types)):
            if six.PY3:
                cp.read_file(stream_or_string)
            else:
                cp.readfp(stream_or_string)
        else:
            if six.PY3:
                cp.read_file(six.moves.StringIO(stream_or_string))
            else:
                # python2's ConfigParser cannot parse a config from a string
                cp.readfp(six.moves.StringIO(stream_or_string))
        data = {}
        for section_name in cp.sections():
            section = {}
            for k, v in cp.items(section_name):
                section[k] = v
            data[section_name] = section
        return data
    except Exception as error:
        raise DeserializationError(error)