Skip to content

Improve "Name is not defined" errors with fuzzy matching#20693

Open
KevinRK29 wants to merge 10 commits intopython:masterfrom
KevinRK29:add-fuzzy-matching
Open

Improve "Name is not defined" errors with fuzzy matching#20693
KevinRK29 wants to merge 10 commits intopython:masterfrom
KevinRK29:add-fuzzy-matching

Conversation

@KevinRK29
Copy link
Collaborator

This PR collects all visible names in the current scope and uses fuzzy matching to provide suggestions in the error messages

@KevinRK29 KevinRK29 marked this pull request as draft January 30, 2026 06:13
@KevinRK29 KevinRK29 requested a review from JukkaL January 30, 2026 06:14
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@KevinRK29 KevinRK29 marked this pull request as ready for review February 20, 2026 16:21
@@ -608,7 +608,7 @@ def f(x: _T) -> None: pass
s: FrozenSet
[out]
_program.py:2: error: Name "_T" is not defined
_program.py:3: error: Name "FrozenSet" is not defined
_program.py:3: error: Name "FrozenSet" is not defined; did you mean "frozenset"?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add an explicit test in some check-*.test file that ensures that misspellings of builtins are detected?


y = MyClas() # E: Name "MyClas" is not defined; did you mean "MyClass"? [name-defined]

unknown_xyz # E: Name "unknown_xyz" is not defined [name-defined]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideas for additional tests:

  • Test a misspelling of a local variable.
  • Test a mispelling of a top-level definition within a function (misspelling targeting an outer namespace).
  • Test a misspelling of a class variable within class body.
  • Test a misspelling of name that is available through from import name.

and not (name.startswith("__") and name.endswith("__"))
and f"builtins.{name}" not in SUGGESTED_TEST_FIXTURES
):
alternatives = self._get_names_in_scope()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is pretty expensive, we shouldn't do the analysis if the error will just be ignored. This way we'd only slow things down when there is a user-visible error. In some codebases, there could be thousands of ignored errors, and this could generate non-trivial amounts of extra work.

My suggestion would be to refactor is_ignored_error in mypy/errors.py so that most of the checking (but not the blocker check) is available through is_ignored_error_code(line, code, ignores), for example. Then you can check if codes.NAME_DEFINED is ignored here, and skip the expensive logic.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, it would be fine to skip the logic if there is any ignore comment on the line, if that's easier to implement.

names.update(table.keys())

if self.type is not None:
names.update(self.type.names.keys())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Class namespace should only be included if we are not within a method (i.e. directly within class body only).

@KevinRK29 KevinRK29 force-pushed the add-fuzzy-matching branch from 5825537 to 1dcdd5f Compare March 15, 2026 23:46
@KevinRK29 KevinRK29 force-pushed the add-fuzzy-matching branch from 035f1e6 to ce1d1ef Compare March 15, 2026 23:53
@KevinRK29 KevinRK29 force-pushed the add-fuzzy-matching branch from 917a3eb to cae911d Compare March 16, 2026 00:01
@github-actions

This comment has been minimized.

@KevinRK29 KevinRK29 force-pushed the add-fuzzy-matching branch from 094a532 to 9d0b73d Compare March 16, 2026 02:04
@github-actions

This comment has been minimized.

@KevinRK29 KevinRK29 force-pushed the add-fuzzy-matching branch from b94afc4 to ba25bd9 Compare March 16, 2026 06:05
@KevinRK29 KevinRK29 requested a review from JukkaL March 16, 2026 06:06
@github-actions
Copy link
Contributor

Diff from mypy_primer, showing the effect of this PR on open source code:

manticore (https://github.com/trailofbits/manticore)
- tests/auto_generators/make_dump.py:390: error: Name "xrange" is not defined  [name-defined]
+ tests/auto_generators/make_dump.py:390: error: Name "xrange" is not defined; did you mean "range"?  [name-defined]

apprise (https://github.com/caronc/apprise)
- apprise/plugins/irc/client.py:115: error: Name "Deque" is not defined  [name-defined]
+ apprise/plugins/irc/client.py:115: error: Name "Deque" is not defined; did you mean "deque"?  [name-defined]

AutoSplit (https://github.com/Toufool/AutoSplit)
- src/utils.py:178:20: error: Name "FilterGraph" is not defined  [name-defined]
+ src/utils.py:178:20: error: Name "FilterGraph" is not defined; did you mean "filter_graph"?  [name-defined]
- src/utils.py:184:12: error: Name "COMError" is not defined  [name-defined]
+ src/utils.py:184:12: error: Name "COMError" is not defined; did you mean "IOError" or "OSError"?  [name-defined]

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.

2 participants