Skip to content

gh-159684: Modernize string formatting and simplify constructs in configparser - #159687

Open
jaraco wants to merge 5 commits into
python:mainfrom
jaraco:gh-159684-configparser-ruff
Open

jaraco wants to merge 5 commits into
python:mainfrom
jaraco:gh-159684-configparser-ruff

Conversation

@jaraco

@jaraco jaraco commented Oct 18, 2026 •

Copy link
Copy Markdown
Member

Brings Lib/configparser.py and Lib/test/test_configparser.py up to Ruff's
default rule set, which reported 72 findings across the two files. CPython's
own Ruff configuration only selects F401 and F811 for Lib/, so nothing
here was failing; the motivation is readability plus keeping the module
convergent with its PyPI backport, which lints with the defaults and would
otherwise need a per-file exemption for exactly these two files
(jaraco/configparser#73).

Four commits, each reviewable on its own:

  1. f-strings (UP030, UP031, UP032) — the autofixable conversions,
    with the lines that would have exceeded 79 columns rewrapped by hand. The
    rendered strings are unchanged; %% escapes collapse to % as the %
    operator did.
  2. Simplifications — C405, C408, C414, RUF019, RUF059, F841,
    SIM102, SIM117, and parenthesizing an implicit string concatenation
    inside a list literal (ISC004) so it does not read as a missing comma.
  3. The remaining % sites that Ruff declines to autofix because the %d
    conversions are not provably integral. Converted by hand, keeping an
    explicit :d so a non-integer still raises rather than being coerced.
  4. Imports, __all__, and ClassVar (I001, RUF022, RUF012).

The last one is the only part with a design decision in it. RUF012 wants
BOOLEAN_STATES annotated ClassVar, and the obvious spelling would import
typing at runtime — which this module deliberately avoids, per the
gh-117703 note above its imports. So it adds from __future__ import annotations and imports ClassVar only under TYPE_CHECKING, the same shape
Lib/tomllib/_parser.py and Lib/importlib/metadata/__init__.py use (both
also kept in sync with a PyPI backport). python -X importtime -c "import configparser" confirms typing stays out of the import graph. Deferring
annotations also lets Iterable['ParsingError'] drop its quotes (UP037).

That does make TYPE_CHECKING a module-level name, so it joins Error in
not_exported in the check__all__ test.

C901 on ExtendedInterpolation._interpolate_some (13 > 10) is the one
finding not fixed. It is a measurement, not a defect, and no small edit
satisfies it, so it gets # noqa: C901 # gh-159686; gh-159686 records why the
branching is inherent to the interpolation grammar and sketches a possible
refactoring, so the suppression is documented rather than silent.

With all four applied, both CPython's Ruff configuration and the default rule
set report no findings for either file, at py310 and py314 targets.
test_configparser, test_logging, test_collections, test___all__ and
test_pydoc pass.

NEWS entry added under Library; there is no user-visible behavior change.

🤖 Generated with Claude Code

jaraco and others added 4 commits October 18, 2026 15:45
Convert the remaining printf-style and str.format() call sites in
Lib/configparser.py and Lib/test/test_configparser.py to f-strings
(Ruff UP030, UP031, UP032), rewrapping the lines that would otherwise
exceed 79 columns. No behavior change; the rendered strings are
identical.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Apply the straightforward simplifications Ruff reports for these two
modules: redundant list() calls (C408, C414), a literal set (C405),
a key check that get() already covers (RUF019), an unpacked value that
is never used (RUF059), an unused assertRaises binding (F841),
collapsible if statements (SIM102) and nested with statements (SIM117).
Also parenthesize an implicit string concatenation inside a list
literal (ISC004) so it is not mistaken for a missing comma.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ruff leaves these UP031 sites alone because the %d conversions are not
provably integral, so convert them by hand, keeping the explicit :d
format spec so a non-integer still raises rather than being coerced.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sort the imports (I001) and __all__ (RUF022), and annotate the mutable
class attributes as ClassVar (RUF012). The ClassVar annotation would
otherwise mean importing typing at runtime, which this module avoids,
so defer annotations with __future__ instead and import ClassVar only
under TYPE_CHECKING, as tomllib and importlib.metadata do. Deferring
annotations also lets ParsingError be referenced unquoted (UP037).

ExtendedInterpolation._interpolate_some gets an explicit noqa: C901,
tagged with pythongh-159686, which records why the complexity is inherent to
the interpolation grammar and what a refactoring might look like.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant