def read_stream (stream):
    """Python 3 compat note: we're assuming `stream` gives bytes not unicode."""

    section = None
    key = None
    data = None

    for fullline in stream:
        line = fullline.split ('#', 1)[0]

        m = sectionre.match (line)
        if m is not None:
            # New section
            if section is not None:
                if key is not None:
                    section.set_one (key, data.strip ().decode ('utf8'))
                    key = data = None
                yield section

            section = Holder ()
            section.section = m.group (1)
            continue

        if len (line.strip ()) == 0:
            if key is not None:
                section.set_one (key, data.strip ().decode ('utf8'))
                key = data = None
            continue

        m = escre.match (fullline)
        if m is not None:
            if section is None:
                raise InifileError ('key seen without section!')
            if key is not None:
                section.set_one (key, data.strip ().decode ('utf8'))
            key = m.group (1)
            data = m.group (2).replace (r'\"', '"').replace (r'\n', '\n').replace (r'\\', '\\')
            section.set_one (key, data.decode ('utf8'))
            key = data = None
            continue

        m = keyre.match (line)
        if m is not None:
            if section is None:
                raise InifileError ('key seen without section!')
            if key is not None:
                section.set_one (key, data.strip ().decode ('utf8'))
            key = m.group (1)
            data = m.group (2)
            if not len (data):
                data = ' '
            elif not data[-1].isspace ():
                data += ' '
            continue

        if line[0].isspace () and key is not None:
            data += line.strip () + ' '
            continue

        raise InifileError ('unparsable line: ' + line[:-1])

    if section is not None:
        if key is not None:
            section.set_one (key, data.strip ().decode ('utf8'))
        yield section
Python 3 compat note: we're assuming `stream` gives bytes not unicode.