def from_file(cls, f):
        """Read configuration from a file-like object."""
        ret = cls()
        section = None
        setting = None
        for lineno, line in enumerate(f.readlines()):
            line = line.lstrip()
            if setting is None:
                if _strip_comments(line).strip() == "":
                    continue
                if line[0] == "[":
                    line = _strip_comments(line).rstrip()
                    if line[-1] != "]":
                        raise ValueError("expected trailing ]")
                    key = line.strip()
                    pts = key[1:-1].split(" ", 1)
                    pts[0] = pts[0].lower()
                    if len(pts) == 2:
                        if pts[1][0] != "\"" or pts[1][-1] != "\"":
                            raise ValueError(
                                "Invalid subsection " + pts[1])
                        else:
                            pts[1] = pts[1][1:-1]
                        if not _check_section_name(pts[0]):
                            raise ValueError("invalid section name %s" %
                                             pts[0])
                        section = (pts[0], pts[1])
                    else:
                        if not _check_section_name(pts[0]):
                            raise ValueError("invalid section name %s" %
                                    pts[0])
                        pts = pts[0].split(".", 1)
                        if len(pts) == 2:
                            section = (pts[0], pts[1])
                        else:
                            section = (pts[0], )
                    ret._values[section] = {}
                else:
                    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"):
                        value = value[:-2]
                        continuation = True
                    else:
                        continuation = False
                    value = _parse_string(value)
                    ret._values[section][setting] = value
                    if not continuation:
                        setting = None
            else:  # continuation line
                if line.endswith("\\\n"):
                    line = line[:-2]
                    continuation = True
                else:
                    continuation = False
                value = _parse_string(line)
                ret._values[section][setting] += value
                if not continuation:
                    setting = None
        return ret
Read configuration from a file-like object.