diff options
author | Claudiu Popa <pcmanticore@gmail.com> | 2015-12-18 21:08:50 +0200 |
---|---|---|
committer | Claudiu Popa <pcmanticore@gmail.com> | 2015-12-29 16:58:35 +0200 |
commit | df0e1c23518f3bbbac584de5856dc53ac48c906c (patch) | |
tree | f9da9d59e0ab492fca9995496d244b03fc1fde48 /astroid/tree/scoped_nodes.py | |
parent | 13e69de65d34d65035e1e6af4c9d67337b60f0a2 (diff) | |
download | astroid-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.py | 40 |
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, |