Skip to content

configparser.ConfigParser.values() should return a ValuesView[configparser.SectionProxy] #11547

Open
@fizbin

Description

@fizbin

Consider these two similar python programs, which have identical behavior:

#! /usr/bin/env/python

import configparser
import re
import sys

if __name__ == "__main__":
    for filename in sys.argv[1:]:
        cparser = configparser.ConfigParser(interpolation=None)
        cparser.read(filename)
        changed = False
        for _ignored, section in cparser.items():
            if section.name == "DEFAULT":
                continue
            for k, v in section.items():
                if re.fullmatch(r"\d+", v):
                    section[k] = str(int(v) + 1)
                    changed = True
        if changed:
            with open(filename, "wt", encoding="utf-8") as fp:
                cparser.write(fp)

and

#! /usr/bin/env/python

import configparser
import re
import sys

if __name__ == "__main__":
    for filename in sys.argv[1:]:
        cparser = configparser.ConfigParser(interpolation=None)
        cparser.read(filename)
        changed = False
        for section in cparser.values():
            if section.name == "DEFAULT":
                continue
            for k, v in section.items():
                if re.fullmatch(r"\d+", v):
                    section[k] = str(int(v) + 1)
                    changed = True
        if changed:
            with open(filename, "wt", encoding="utf-8") as fp:
                cparser.write(fp)

(The only difference between the two programs is invoking cparser.items() or cparser.values())

The first program type-checks in mypy without any issues, but the second program:

/tmp/incints.py:13: error: "Mapping[str, str]" has no attribute "name"  [attr-defined]
/tmp/incints.py:17: error: Unsupported target for indexed assignment ("Mapping[str, str]")  [index]
Found 2 errors in 1 file (checked 1 source file)

The problem is that ConfigParser objects accept assignment of arbitrary str -> str mappings but when you pull a value back out of a ConfigParser, the value pulled out is always a configparser.SectionProxy. (see the __getitem__ and __setitem__ methods on configparser.RawConfigParser)

Note that this affects not only the return type of values but also the return type of __getitem__; it should be perfectly well-typed to write cparser[some_str_value].name.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions