Skip to content

E721: flag swapped type comparisons like int == type(obj)#1317

Closed
apoorvdarshan wants to merge 1 commit into
PyCQA:mainfrom
apoorvdarshan:fix-e721-symmetric-type-comparison
Closed

E721: flag swapped type comparisons like int == type(obj)#1317
apoorvdarshan wants to merge 1 commit into
PyCQA:mainfrom
apoorvdarshan:fix-e721-symmetric-type-comparison

Conversation

@apoorvdarshan

Copy link
Copy Markdown

Summary

E721 (do not compare types) only fired when a type(...) call appeared on the left of == / !=:

if type(obj) == int:   # E721
if int == type(obj):   # (nothing) — but this is the same comparison

comparison_type inspected only match.group(1) — the argument of the right-hand type(...) call — and suppressed the warning whenever that argument was a plain identifier (if inst and inst.isidentifier() and inst not in SINGLETONS: return). Because the two alternatives of COMPARE_TYPE_REGEX capture opposite operands, this made the check asymmetric: type(obj) == x was reported while the mirror x == type(obj) was not, and the issue's int == type(obj) slipped through entirely.

Fix

Remove the identifier-based suppression so both operand orders are treated identically, and drop the now-unused capture groups from COMPARE_TYPE_REGEX (they are no longer referenced). The regex already matches a bare type(...) call on either side of == / !=, so the check is now symmetric.

No existing Okay fixture relied on the suppression — every one of them fails to match COMPARE_TYPE_REGEX in the first place (they use is / is not, .type(, compute_type(, or types.SomeType), so those cases are unaffected.

Tests / Verification

  • Added regression fixtures to testing/data/E72.py for the swapped == and != forms (if int == type(res):, if str != type(res):), each annotated #: E721. These fail on the pristine code and pass with the fix.
  • Added E721 doctest examples to the comparison_type docstring (verified by tests/test_self_doctests.py).
  • pytest tests/ — all 777 tests pass.
  • pytest tests/test_data.py -k E72 — 26 fixture cases pass.
  • pre-commit run --files pycodestyle.py testing/data/E72.py — all hooks (flake8, pyupgrade, reorder-python-imports, etc.) pass.
  • Dog-food self-lint (tests/test_all.py) passes; running the CLI on the issue's repro now emits E721.

Fixes #1187.

Disclosure: prepared with AI assistance; reviewed and verified locally.

E721 only fired when a `type(...)` call was on the left-hand side of
`==` / `!=` (e.g. `type(obj) == int`). The swapped form
`int == type(obj)` was silently ignored even though it is the same
type comparison.

`comparison_type` only inspected `match.group(1)`, the argument of the
right-hand `type(...)` call, and suppressed the warning whenever that
argument was a plain identifier. Because the two regex alternatives
capture opposite sides, this made the check asymmetric: `type(obj) == x`
was reported but the mirror `x == type(obj)` was not.

Remove the identifier-based suppression so both operand orders are
treated identically, and drop the now-unused capture groups from
COMPARE_TYPE_REGEX. Add regression fixtures for the swapped `==` and
`!=` forms to testing/data/E72.py.

Fixes PyCQA#1187.
@asottile asottile closed this Jul 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

E721: pycodestyle v2.11.0 does not raise the error to int == type(obj)

2 participants