From 76ac95ec22de0ab4dfa1727fc943465830754ecb Mon Sep 17 00:00:00 2001 From: "Yu Shao, Pang" Date: Sat, 4 Sep 2021 23:50:57 +0800 Subject: [PATCH] Fix false positive ``unused-private-member`` for accessing attributes in a class using ``cls`` --- ChangeLog | 4 ++++ doc/whatsnew/2.11.rst | 4 ++++ pylint/checkers/classes.py | 8 ++++---- .../u/unused/unused_private_member.py | 17 +++++++++++++++++ .../u/unused/unused_private_member.txt | 4 ++-- 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index ee1b82af53..f173213930 100644 --- a/ChangeLog +++ b/ChangeLog @@ -63,6 +63,10 @@ Release date: TBA Closes #4907 +* Fix false positive ``unused-private-member`` for accessing attributes in a class using ``cls`` + + Closes #4849 + What's New in Pylint 2.10.3? ============================ diff --git a/doc/whatsnew/2.11.rst b/doc/whatsnew/2.11.rst index cdbba865d4..c450abdf3c 100644 --- a/doc/whatsnew/2.11.rst +++ b/doc/whatsnew/2.11.rst @@ -69,3 +69,7 @@ Other Changes * Fix false positive ``superfluous-parens`` for tuples created with inner tuples Closes #4907 + +* Fix false positive ``unused-private-member`` for accessing attributes in a class using ``cls`` + + Closes #4849 diff --git a/pylint/checkers/classes.py b/pylint/checkers/classes.py index 59e4742204..eeef46c16d 100644 --- a/pylint/checkers/classes.py +++ b/pylint/checkers/classes.py @@ -1000,11 +1000,11 @@ def _check_unused_private_attributes(self, node: nodes.ClassDef) -> None: if attribute.attrname != assign_attr.attrname: continue - if assign_attr.expr.name == "cls" and attribute.expr.name in [ + if assign_attr.expr.name in [ "cls", - "self", - ]: - # If assigned to cls.attrib, can be accessed by cls/self + node.name, + ] and attribute.expr.name in ["cls", "self", node.name]: + # If assigned to cls or class name, can be accessed by cls/self/class name break if ( diff --git a/tests/functional/u/unused/unused_private_member.py b/tests/functional/u/unused/unused_private_member.py index 1acdd91249..93fdd1c746 100644 --- a/tests/functional/u/unused/unused_private_member.py +++ b/tests/functional/u/unused/unused_private_member.py @@ -242,6 +242,23 @@ def __init__(self): FalsePositive4681.__instance = False # This should be fine FalsePositive4681.__should_cause_error = False # [unused-private-member] +# Accessing attributes of the class using `cls` should not result in a false positive +# as long as it is used within the class +class FalsePositive4681b: + __instance = None + + @classmethod # Use class method here + def instance(cls): + if cls.__instance is None: + cls() + return cls.__instance + + def __init__(self): + try: + FalsePositive4681b.__instance = 42 # This should be fine + except Exception: # pylint: disable=broad-except + print("Error") + FalsePositive4681b.__instance = False # This should be fine class Pony: """https://github.com/PyCQA/pylint/issues/4837""" diff --git a/tests/functional/u/unused/unused_private_member.txt b/tests/functional/u/unused/unused_private_member.txt index 391316d354..4c6245be21 100644 --- a/tests/functional/u/unused/unused_private_member.txt +++ b/tests/functional/u/unused/unused_private_member.txt @@ -14,5 +14,5 @@ unused-private-member:212:8:Crash4755Context.__init__:Unused private member `Cra unused-private-member:229:4:FalsePositive4681:Unused private member `FalsePositive4681.__should_cause_error`:HIGH unused-private-member:239:12:FalsePositive4681.__init__:Unused private member `FalsePositive4681.__should_cause_error`:HIGH unused-private-member:243:12:FalsePositive4681.__init__:Unused private member `FalsePositive4681.__should_cause_error`:HIGH -unused-private-member:254:4:Pony.__init_defaults:Unused private member `Pony.__init_defaults(self)`:HIGH -unused-private-member:259:4:Pony.__get_fur_color:Unused private member `Pony.__get_fur_color(self)`:HIGH +unused-private-member:271:4:Pony.__init_defaults:Unused private member `Pony.__init_defaults(self)`:HIGH +unused-private-member:276:4:Pony.__get_fur_color:Unused private member `Pony.__get_fur_color(self)`:HIGH