Skip to content

Commit 0a1ebd4

Browse files
DanielNoordPierre-Sassoulas
authored andcommitted
Fix crash on checking private members on __class__
Closes #5261
1 parent 96e8459 commit 0a1ebd4

File tree

4 files changed

+27
-6
lines changed

4 files changed

+27
-6
lines changed

ChangeLog

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ Release date: TBA
140140

141141
Closes #5216
142142

143+
* Fix crash for ``unused-private-member`` when checking private members on ``__class__``
144+
145+
Closes #5261
146+
143147
* Added new checker ``useless-with-lock`` to find incorrect usage of with statement and threading module locks.
144148
Emitted when ``with threading.Lock():`` is used instead of ``with lock_instance:``.
145149

doc/whatsnew/2.12.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ Other Changes
118118

119119
Closes #3688
120120

121+
* Fix crash for ``unused-private-member`` when checking private members on ``__class__``
122+
123+
Closes #5261
124+
121125
* Fix double emitting of ``not-callable`` on inferrable ``properties``
122126

123127
Closes #4426

pylint/checkers/classes.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,7 @@ def _check_unused_private_functions(self, node: nodes.ClassDef) -> None:
945945
)
946946

947947
def _check_unused_private_variables(self, node: nodes.ClassDef) -> None:
948+
"""Check if private variables are never used within a class"""
948949
for assign_name in node.nodes_of_class(nodes.AssignName):
949950
if isinstance(assign_name.parent, nodes.Arguments):
950951
continue # Ignore function arguments
@@ -953,12 +954,15 @@ def _check_unused_private_variables(self, node: nodes.ClassDef) -> None:
953954
for child in node.nodes_of_class((nodes.Name, nodes.Attribute)):
954955
if isinstance(child, nodes.Name) and child.name == assign_name.name:
955956
break
956-
if (
957-
isinstance(child, nodes.Attribute)
958-
and child.attrname == assign_name.name
959-
and child.expr.name in ("self", "cls", node.name)
960-
):
961-
break
957+
if isinstance(child, nodes.Attribute):
958+
if not isinstance(child.expr, nodes.Name):
959+
break
960+
if child.attrname == assign_name.name and child.expr.name in (
961+
"self",
962+
"cls",
963+
node.name,
964+
):
965+
break
962966
else:
963967
args = (node.name, assign_name.name)
964968
self.add_message("unused-private-member", node=assign_name, args=args)

tests/functional/u/unused/unused_private_member.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,3 +300,12 @@ def __get_fur_color(self): # [unused-private-member]
300300

301301
def lookup_attribute(mapping, key):
302302
return mapping[key]
303+
304+
305+
# Test for regression on checking __class__ attribute
306+
# See: https://github.com/PyCQA/pylint/issues/5261
307+
class Foo:
308+
__ham = 1
309+
310+
def method(self):
311+
print(self.__class__.__ham)

0 commit comments

Comments
 (0)