'Read configuration from a file-like object.'

@classmethod
def from_file(cls, f):

    ret = cls()
    section = None
    setting = None
    for (lineno, line) in enumerate(f.readlines()):
        line = line.lstrip()
        if (setting is None):
            if ((len(line) > 0) and (line[:1] == '[')):
                line = _strip_comments(line).rstrip()
                last = line.index(']')
                if (last == (-1)):
                    raise ValueError('expected    trailing    ]')
                pts = line[1:last].split('    ', 1)
                line = line[(last + 1):]
                pts[0] = pts[0].lower()
                if (len(pts) == 2):
                    if ((pts[1][:1] != '"') or (pts[1][(-1):] != '"')):
                        raise ValueError(('Invalid    subsection    %r' % pts[1]))
                    else:
                        pts[1] = pts[1][1:(-1)]
                    if (not _check_section_name(pts[0])):
                        raise ValueError(('invalid    section    name    %r' % pts[0]))
                    section = (pts[0], pts[1])
                else:
                    if (not _check_section_name(pts[0])):
                        raise ValueError(('invalid    section    name    %r' % pts[0]))
                    pts = pts[0].split('.', 1)
                    if (len(pts) == 2):
                        section = (pts[0], pts[1])
                    else:
                        section = (pts[0],)
                ret._values[section] = OrderedDict()
            if (_strip_comments(line).strip() == ''):
                continue
            if (section is None):
                raise ValueError(('setting    %r    without    section' % line))
            try:
                (setting, value) = line.split('=', 1)
            except ValueError:
                setting = line
                value = 'true'
            setting = setting.strip().lower()
            if (not _check_variable_name(setting)):
                raise ValueError(('invalid    variable    name    %s' % setting))
            if value.endswith('\\\n'):
                continuation = value[:(-2)]
            else:
                continuation = None
                value = _parse_string(value)
                ret._values[section][setting] = value
                setting = None
        elif line.endswith('\\\n'):
            continuation += line[:(-2)]
        else:
            continuation += line
            value = _parse_string(continuation)
            ret._values[section][setting] = value
            continuation = None
            setting = None
    return ret
