Skip to content

Fix pyreverse crash on classes with EmptyNode instance attrs - #11278

Draft
aryansk wants to merge 3 commits into
pylint-dev:mainfrom
aryansk:fix/10767-pyreverse-empty-node
Draft

Fix pyreverse crash on classes with EmptyNode instance attrs#11278
aryansk wants to merge 3 commits into
pylint-dev:mainfrom
aryansk:fix/10767-pyreverse-empty-node

Conversation

@aryansk

@aryansk aryansk commented Aug 15, 2026

Copy link
Copy Markdown

Description

Fixes #10767

pyreverse crashes with AttributeError: 'EmptyNode' object has no attribute 'name' when a class diagram includes a class whose instance_attrs contain synthetic EmptyNode entries. Astroid injects these placeholders when rebuilding certain classes — e.g. namedtuple results (the namedtuple brain sets attrname on EmptyNode nodes) and argparse.Namespace inference results.

The Linker.visit_classdef guarded against nodes.Unknown placeholders but not nodes.EmptyNode, so the placeholder was passed into the composition/aggregation/association relationship handlers, which dereferenced .name and crashed.

This change skips both placeholder types when extracting relationships.

Type of Changes

Type
🐛 Bug fix

Related Issue

Closes #10767

aryansk and others added 3 commits August 15, 2026 20:56
A function's type parameters (PEP 695) are scoped to the function, so
reusing a type-parameter name from an outer scope (e.g. a type alias)
is a common idiom and should not trigger redefined-outer-name (W0621).

Skip names that are type parameters of the current function in
visit_functiondef, add a functional regression test, and update the
used_before_assignment_py312/py313 functional tests that previously
documented this false positive. Closes pylint-dev#11169.
The Linker's visit_classdef skipped `nodes.Unknown` placeholders but not
`nodes.EmptyNode`, which astroid's namedtuple/argparse brains inject into
`instance_attrs` of rebuilt classes. The relationship handlers then
dereferenced `.name` on the placeholder and crashed. Skip both placeholder
types when extracting composition/association relationships.

Closes pylint-dev#10767
@HDPark95

Copy link
Copy Markdown

Reproduced the crash on main; this patch clears it.

Regression from #10397 (1abd975): at 1abd975c^, pyreverse -A -S over a namedtuple class emitted Point { x y } and the composition edge, here it emits Point { }. The brains set attrname, so handle_assignattr_type still works; only the new handler chain reads .name. Skipping just compositions_handler.handle restored the old output.

That turns tests/pyreverse 9 red, all from the new test leaving synthetic on a session-cached ClassDef. #8032 kept its crash regression in functional/class_diagrams/regression/.

@Pierre-Sassoulas Pierre-Sassoulas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Let's remove the unrelated changes in redfined-outer-name please.

@github-actions

Copy link
Copy Markdown
Contributor

🤖 Effect of this PR on checked open source code: 🤖

Effect on sentry:

Removed messages:

Details
  1. redefined-outer-name:
    Redefining name 'T' from outer scope (line 28)
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/api/decorators.py#L31
  2. redefined-outer-name:
    Redefining name 'P' from outer scope (line 28)
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/api/decorators.py#L31
  3. redefined-outer-name:
    Redefining name 'T' from outer scope (line 28)
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/api/decorators.py#L45
  4. redefined-outer-name:
    Redefining name 'P' from outer scope (line 28)
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/api/decorators.py#L45
  5. redefined-outer-name:
    Redefining name 'T' from outer scope (line 329)
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/api/event_search.py#L332
  6. redefined-outer-name:
    Redefining name 'T' from outer scope (line 329)
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/api/event_search.py#L345
  7. redefined-outer-name:
    Redefining name 'T' from outer scope (line 329)
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/api/event_search.py#L354
  8. redefined-outer-name:
    Redefining name 'T' from outer scope (line 34)
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/workflow_engine/buffer/redis_hash_sorted_set_buffer.py#L425
  9. redefined-outer-name:
    Redefining name 'T' from outer scope (line 34)
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/workflow_engine/buffer/redis_hash_sorted_set_buffer.py#L431

This comment was generated for commit b4464f1

@codecov

codecov Bot commented Aug 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.44%. Comparing base (5632ffe) to head (b4464f1).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main   #11278      +/-   ##
==========================================
+ Coverage   96.40%   96.44%   +0.04%     
==========================================
  Files         178      178              
  Lines       20020    20023       +3     
==========================================
+ Hits        19300    19311      +11     
+ Misses        720      712       -8     
Files with missing lines Coverage Δ
pylint/checkers/variables.py 97.32% <100.00%> (+<0.01%) ⬆️
pylint/pyreverse/inspector.py 89.13% <100.00%> (+0.36%) ⬆️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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.

Pylint/pyreverse bug

3 participants