summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Byrne <31762852+mbyrnepr2@users.noreply.github.com>2022-08-12 01:45:35 +0200
committerGitHub <noreply@github.com>2022-08-11 19:45:35 -0400
commit9dead651a8f6394ae6c56956cceee4ebc8ad3c58 (patch)
tree196831889d1e3dfca7ac6f85931fa89cc8ed6ee2
parent815b765b6a5836e0150b2b64b919216e6a52f0e3 (diff)
downloadpylint-git-9dead651a8f6394ae6c56956cceee4ebc8ad3c58.tar.gz
Fix crash when a type-annotated `__slots__` with no value is declared. (#7285)
* Fix crash when a type-annotated `__slots__` with no value is declared. Closes #7280
-rw-r--r--doc/whatsnew/fragments/7280.other3
-rw-r--r--pylint/checkers/classes/class_checker.py5
-rw-r--r--tests/functional/s/slots_checks.py23
-rw-r--r--tests/functional/s/slots_checks.txt28
4 files changed, 44 insertions, 15 deletions
diff --git a/doc/whatsnew/fragments/7280.other b/doc/whatsnew/fragments/7280.other
new file mode 100644
index 000000000..84cac7c8f
--- /dev/null
+++ b/doc/whatsnew/fragments/7280.other
@@ -0,0 +1,3 @@
+Fix crash when a type-annotated `__slots__` with no value is declared.
+
+Closes #7280
diff --git a/pylint/checkers/classes/class_checker.py b/pylint/checkers/classes/class_checker.py
index 1fb644466..b48836089 100644
--- a/pylint/checkers/classes/class_checker.py
+++ b/pylint/checkers/classes/class_checker.py
@@ -1396,7 +1396,8 @@ a metaclass class method.",
def _check_slots(self, node: nodes.ClassDef) -> None:
if "__slots__" not in node.locals:
return
- for slots in node.igetattr("__slots__"):
+
+ for slots in node.ilookup("__slots__"):
# check if __slots__ is a valid type
if slots is astroid.Uninferable:
continue
@@ -1417,7 +1418,7 @@ a metaclass class method.",
else:
values = slots.itered()
if values is astroid.Uninferable:
- return
+ continue
for elt in values:
try:
self._check_slots_elt(elt, node)
diff --git a/tests/functional/s/slots_checks.py b/tests/functional/s/slots_checks.py
index a465ef545..2cae34acd 100644
--- a/tests/functional/s/slots_checks.py
+++ b/tests/functional/s/slots_checks.py
@@ -33,6 +33,18 @@ class FifthGood(object):
class SixthGood(object):
__slots__ = {"a": "b", "c": "d"}
+class SeventhGood:
+ """type-annotated __slots__ with no value"""
+ __slots__: str
+
+class EigthGood:
+ """Multiple __slots__ declared in the class"""
+ x = 1
+ if x:
+ __slots__: str
+ else:
+ __slots__ = ("y",)
+
class Bad(object): # [invalid-slots]
__slots__ = list
@@ -63,6 +75,17 @@ class NinthBad(object):
class TenthBad(object):
__slots__ = [1 + 2 + 3] # [invalid-slots-object]
+class EleventhBad: # [invalid-slots]
+ __slots__ = None
+
+class TwelfthBad: # [invalid-slots]
+ """One valid & one invalid __slots__ value"""
+ x = 1
+ if x:
+ __slots__ = ("y",)
+ else:
+ __slots__ = None
+
class PotentiallyGood(object):
__slots__ = func()
diff --git a/tests/functional/s/slots_checks.txt b/tests/functional/s/slots_checks.txt
index 49b314912..3abccff8f 100644
--- a/tests/functional/s/slots_checks.txt
+++ b/tests/functional/s/slots_checks.txt
@@ -1,13 +1,15 @@
-invalid-slots:36:0:36:9:Bad:Invalid __slots__ object:UNDEFINED
-invalid-slots:39:0:39:15:SecondBad:Invalid __slots__ object:UNDEFINED
-invalid-slots-object:43:22:43:23:ThirdBad:Invalid object '2' in __slots__, must contain only non empty strings:INFERENCE
-invalid-slots:45:0:45:15:FourthBad:Invalid __slots__ object:UNDEFINED
-invalid-slots-object:49:27:49:29:FifthBad:"Invalid object ""''"" in __slots__, must contain only non empty strings":INFERENCE
-single-string-used-for-slots:51:0:51:14:SixthBad:Class __slots__ should be a non-string iterable:UNDEFINED
-single-string-used-for-slots:54:0:54:16:SeventhBad:Class __slots__ should be a non-string iterable:UNDEFINED
-single-string-used-for-slots:57:0:57:15:EighthBad:Class __slots__ should be a non-string iterable:UNDEFINED
-invalid-slots-object:61:17:61:20:NinthBad:Invalid object 'str' in __slots__, must contain only non empty strings:INFERENCE
-invalid-slots-object:64:17:64:26:TenthBad:Invalid object '1 + 2 + 3' in __slots__, must contain only non empty strings:INFERENCE
-class-variable-slots-conflict:91:17:91:24:ValueInSlotConflict:Value 'first' in slots conflicts with class variable:UNDEFINED
-class-variable-slots-conflict:91:45:91:53:ValueInSlotConflict:Value 'fourth' in slots conflicts with class variable:UNDEFINED
-class-variable-slots-conflict:91:36:91:43:ValueInSlotConflict:Value 'third' in slots conflicts with class variable:UNDEFINED
+invalid-slots:48:0:48:9:Bad:Invalid __slots__ object:UNDEFINED
+invalid-slots:51:0:51:15:SecondBad:Invalid __slots__ object:UNDEFINED
+invalid-slots-object:55:22:55:23:ThirdBad:Invalid object '2' in __slots__, must contain only non empty strings:INFERENCE
+invalid-slots:57:0:57:15:FourthBad:Invalid __slots__ object:UNDEFINED
+invalid-slots-object:61:27:61:29:FifthBad:"Invalid object ""''"" in __slots__, must contain only non empty strings":INFERENCE
+single-string-used-for-slots:63:0:63:14:SixthBad:Class __slots__ should be a non-string iterable:UNDEFINED
+single-string-used-for-slots:66:0:66:16:SeventhBad:Class __slots__ should be a non-string iterable:UNDEFINED
+single-string-used-for-slots:69:0:69:15:EighthBad:Class __slots__ should be a non-string iterable:UNDEFINED
+invalid-slots-object:73:17:73:20:NinthBad:Invalid object 'str' in __slots__, must contain only non empty strings:INFERENCE
+invalid-slots-object:76:17:76:26:TenthBad:Invalid object '1 + 2 + 3' in __slots__, must contain only non empty strings:INFERENCE
+invalid-slots:78:0:78:17:EleventhBad:Invalid __slots__ object:UNDEFINED
+invalid-slots:81:0:81:16:TwelfthBad:Invalid __slots__ object:UNDEFINED
+class-variable-slots-conflict:114:17:114:24:ValueInSlotConflict:Value 'first' in slots conflicts with class variable:UNDEFINED
+class-variable-slots-conflict:114:45:114:53:ValueInSlotConflict:Value 'fourth' in slots conflicts with class variable:UNDEFINED
+class-variable-slots-conflict:114:36:114:43:ValueInSlotConflict:Value 'third' in slots conflicts with class variable:UNDEFINED