summaryrefslogtreecommitdiff
path: root/astroid/tree/scoped_nodes.py
diff options
context:
space:
mode:
authorClaudiu Popa <pcmanticore@gmail.com>2015-12-18 21:08:50 +0200
committerClaudiu Popa <pcmanticore@gmail.com>2015-12-29 16:58:35 +0200
commitdf0e1c23518f3bbbac584de5856dc53ac48c906c (patch)
treef9da9d59e0ab492fca9995496d244b03fc1fde48 /astroid/tree/scoped_nodes.py
parent13e69de65d34d65035e1e6af4c9d67337b60f0a2 (diff)
downloadastroid-git-df0e1c23518f3bbbac584de5856dc53ac48c906c.tar.gz
The slots() method conflates all the slots from the ancestors into a list of current and parent slots.
We're doing this because this is the right semantics of slots, they get inherited, as long as each parent defines a __slots__ entry.
Diffstat (limited to 'astroid/tree/scoped_nodes.py')
-rw-r--r--astroid/tree/scoped_nodes.py40
1 files changed, 30 insertions, 10 deletions
diff --git a/astroid/tree/scoped_nodes.py b/astroid/tree/scoped_nodes.py
index ae8da65f..c11eb4ce 100644
--- a/astroid/tree/scoped_nodes.py
+++ b/astroid/tree/scoped_nodes.py
@@ -2030,16 +2030,7 @@ class ClassDef(mixins.FilterStmtsMixin, LocalsDictNodeNG,
except exceptions.InferenceError:
continue
- # Cached, because inferring them all the time is expensive
- @decorators_mod.cached
- def slots(self):
- """Get all the slots for this node.
-
- If the class doesn't define any slot, through `__slots__`
- variable, then this function will return a None.
- Also, it will return None in the case the slots weren't inferred.
- Otherwise, it will return a list of slot names.
- """
+ def _slots(self):
if not self.newstyle:
raise TypeError(
"The concept of slots is undefined for old-style classes.")
@@ -2055,6 +2046,35 @@ class ClassDef(mixins.FilterStmtsMixin, LocalsDictNodeNG,
# pylint: disable=unsupported-binary-operation; false positive
return [first] + list(slots)
+ # Cached, because inferring them all the time is expensive
+ @decorators_mod.cached
+ def slots(self):
+ """Get all the slots for this node.
+
+ If the class doesn't define any slot, through `__slots__`
+ variable, then this function will return a None.
+ Also, it will return None in the case the slots weren't inferred.
+ Otherwise, it will return a list of slot names.
+ """
+ def grouped_slots():
+ # Not interested in object, since it can't have slots.
+ for cls in self.mro()[:-1]:
+ try:
+ cls_slots = cls._slots()
+ except NotImplementedError:
+ continue
+ if cls_slots is not None:
+ for slot in cls_slots:
+ yield slot
+ else:
+ yield None
+
+ slots = list(grouped_slots())
+ if not all(slot is not None for slot in slots):
+ return None
+
+ return sorted(slots, key=lambda item: item.value)
+
def _inferred_bases(self, context=None):
# TODO(cpopa): really similar with .ancestors,
# but the difference is when one base is inferred,