diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | pylint/checkers/classes.py | 7 | ||||
-rw-r--r-- | tests/functional/a/assign/assigning_non_slot_4509.py | 18 | ||||
-rw-r--r-- | tests/functional/a/assign/assigning_non_slot_4509.rc | 2 | ||||
-rw-r--r-- | tests/functional/a/assign/assigning_non_slot_4509.txt | 1 |
5 files changed, 33 insertions, 0 deletions
@@ -119,6 +119,11 @@ modules are added. Closes PyCQA/astroid#942 +* Fix ``assigning-non-slot`` false-positive with base that inherits from ``typing.Generic`` + + Closes #4509 + Closes PyCQA/astroid#999 + What's New in Pylint 2.8.2? =========================== diff --git a/pylint/checkers/classes.py b/pylint/checkers/classes.py index 6870e84c9..18b579e45 100644 --- a/pylint/checkers/classes.py +++ b/pylint/checkers/classes.py @@ -1417,6 +1417,13 @@ a metaclass class method.", if "__slots__" not in klass.locals or not klass.newstyle: return + # If 'typing.Generic' is a base of bases of klass, the cached version + # of 'slots()' might have been evaluated incorrectly, thus deleted cache entry. + if any(base.qname() == "typing.Generic" for base in klass.mro()): + cache = getattr(klass, "__cache", None) + if cache and cache.get(klass.slots) is not None: + del cache[klass.slots] + slots = klass.slots() if slots is None: return diff --git a/tests/functional/a/assign/assigning_non_slot_4509.py b/tests/functional/a/assign/assigning_non_slot_4509.py new file mode 100644 index 000000000..797c6b083 --- /dev/null +++ b/tests/functional/a/assign/assigning_non_slot_4509.py @@ -0,0 +1,18 @@ +# pylint: disable=invalid-name,missing-docstring,too-few-public-methods + +# Slots with base that inherits from 'Generic' +# https://github.com/PyCQA/pylint/issues/4509 +# https://github.com/PyCQA/astroid/issues/999 + +from typing import Generic, TypeVar +T = TypeVar("T") + +class Base(Generic[T]): + __slots__ = () + +class Foo(Base[T]): + __slots__ = ['_value'] + + def __init__(self, value: T): + self._value = value + self._bar = value # [assigning-non-slot] diff --git a/tests/functional/a/assign/assigning_non_slot_4509.rc b/tests/functional/a/assign/assigning_non_slot_4509.rc new file mode 100644 index 000000000..a17bb22da --- /dev/null +++ b/tests/functional/a/assign/assigning_non_slot_4509.rc @@ -0,0 +1,2 @@ +[testoptions] +min_pyver=3.7 diff --git a/tests/functional/a/assign/assigning_non_slot_4509.txt b/tests/functional/a/assign/assigning_non_slot_4509.txt new file mode 100644 index 000000000..a347f8c95 --- /dev/null +++ b/tests/functional/a/assign/assigning_non_slot_4509.txt @@ -0,0 +1 @@ +assigning-non-slot:18:8:Foo.__init__:Assigning to attribute '_bar' not defined in class slots |