pylint-dev / pylint

It's not just a linter that annoys you!
https://pylint.readthedocs.io/en/latest/
GNU General Public License v2.0
5.32k stars 1.14k forks source link

False positive for protected-access / W0212 in a very simple class #9891

Closed bshoshany closed 2 months ago

bshoshany commented 2 months ago

Bug description

Pylint seems to be reporting a false positive, unless I'm misunderstanding something about how classes work. Here is a minimal example:

# pylint: disable=missing-module-docstring, missing-class-docstring, missing-function-docstring, too-few-public-methods

from typing import Self

class MyClass:
    def __init__(self) -> None:
        self._private = 42

    def test(self, other: Self) -> None:
        print(self._private)
        print(other._private)

Even though other is clearly a member of the same class MyClass based on the type annotation, Pylint complains about "Access to a protected member _private of a client class" with error code "protected-access / W0212". Looking at the error code description, it says:

"Used when a protected member (i.e. class member with a name beginning with an underscore) is access outside the class or a descendant of the class where it's defined."

Clearly, _private is being accesses from inside the class where it's defined, so this appears to be a false positive. Even type-annotating the class explicitly doesn't help:

# pylint: disable=missing-module-docstring, missing-class-docstring, missing-function-docstring, too-few-public-methods

from __future__ import annotations

class MyClass:
    def __init__(self) -> None:
        self._private = 42

    def test(self, other: MyClass) -> None:
        print(self._private)
        print(other._private)

Now the other object is explicitly defined as being an instance of MyClass, but Pylint still complains about access to a protected member.

Configuration

No response

Command used

pylint test.py

Pylint output

************* Module test
test.py:11:14: W0212: Access to a protected member _private of a client class (protected-access)

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

Expected behavior

Any method in the class MyClass should be able to access the class's private members on any instance of that very same class.

Pylint version

pylint 3.2.6
astroid 3.3.1
Python 3.12.5 (tags/v3.12.5:ff3bc82, Aug  6 2024, 20:45:27) [MSC v.1940 64 bit (AMD64)]

OS / Environment

Windows 11

Additional dependencies

No response

jacobtylerwalls commented 2 months ago

Thanks for the report. The essence of the issue in this case is that pylint doesn't trust type annotations. There's an obvious value prop there for poorly or untyped projects.

bshoshany commented 2 months ago

Thanks so much for your fast response! If I understand correctly, you are saying that Pylint doesn't trust the type annotation saying that other is of type Self (or MyClass) because it might be wrong if this is a poorly-typed project. If I may ask, what about well-typed projects, where the user spends hours ensuring all type annotations are correct (guilty...), and therefore this is indeed a clear false positive, as in the example above? Perhaps there can at least be some kind of flag that tells Pylint to trust the user's type annotations?

jacobtylerwalls commented 2 months ago

These are good questions, and they can be explored more fully on #4813 in a context broader than just this message 👍 .