pylint icon indicating copy to clipboard operation
pylint copied to clipboard

protected-access false positive in class method of child class

Open couteau opened this issue 1 year ago • 1 comments

Bug description

# pylint: disable=missing-module-docstring,missing-class-docstring,missing-function-docstring,too-few-public-methods
class Parent:
    def __init__(self):
        self._foo = 1

    @classmethod
    def create_instance(cls):
        return cls()

class Child(Parent):
    def __init__(self):
        super().__init__()
        self._bar = 'a'

    @classmethod
    def create_instance(cls):
        inst = super().create_instance()
        inst._foo = 2   # protected-access warning here
        inst._bar = 'b' # protected-access warning here

    @classmethod
    def create_instance2(cls):
        inst = cls()
        inst._foo = 3   # no warning here thanks to #4267
        inst._bar = 'c' # no warning here thanks to #4267

    def get_var(self):
        return self._foo # no warning here

Configuration

No response

Command used

pylint test.py

Pylint output

************* Module test
test.py:18:8: W0212: Access to a protected member _foo of a client class (protected-access)
test.py:19:8: W0212: Access to a protected member _bar of a client class (protected-access)

------------------------------------------------------------------
Your code has been rated at 8.95/10 (previous run: 8.95/10, +0.00)

Expected behavior

This is a derived case from the circumstance addressed by #4267. That pull request addressed accessing a protected member on an instance created in a class method through a direct call to the cls parameter. In this case, the derived class overrides the parent's class method, creates an instance by calling super() and then accesses the protected method on that instance. A child class's class method can access a protected member on an instance it creates directly, and it should also be able to access a protected member on an instance created in an overridden class method by a call to super().

Pylint version

pylint 3.0.3
astroid 3.0.2
Python 3.11.7 | packaged by conda-forge | (main, Dec 23 2023, 14:38:07) [Clang 16.0.6 ]

OS / Environment

MacOS Sonoma MacBook Pro M1 Max

Additional dependencies

none

couteau avatar Feb 06 '24 13:02 couteau

This issue doesn't seem to have gotten any attention, but I'm adding another example with a regular (not class) method, including the __copy__ method, which seems like is a common case that pylint should be able to handle.

class Base:
    def foo(self):
        return self

    def __copy__(self):
        return type(self)()

class Child(Base):
    def bar(self):
        pass

    def foo(self):
        inst = super().foo()
        inst.bar()

    def __copy__(self):
        inst = super().__copy__()
        inst.bar()

running pylint -E on this code produces: test.py:14:8: E1101: Instance of 'Base' has no 'bar' member (no-member) test.py:18:8: E1101: Instance of 'Base' has no 'bar' member (no-member)

couteau avatar Jun 01 '24 13:06 couteau