From 4f2d4992da98e94456dd70060b2f6e3a250faa3f Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Mon, 23 Feb 2015 19:04:35 +0100 Subject: [PATCH] Fix an mro resolution issue. --- jedi/evaluate/representation.py | 35 +++++++++++++++++++++++++++------ jedi/parser/fast.py | 2 -- test/completion/classes.py | 19 +++++++++++++++++- 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/jedi/evaluate/representation.py b/jedi/evaluate/representation.py index 423bc1fd..e04fc03e 100644 --- a/jedi/evaluate/representation.py +++ b/jedi/evaluate/representation.py @@ -404,9 +404,25 @@ class Class(use_metaclass(CachedMetaClass, Wrapper)): for cls in self.py__bases__(self._evaluator): # TODO detect for TypeError: duplicate base class str, # e.g. `class X(str, str): pass` - add(cls) - for cls_new in cls.py__mro__(evaluator): - add(cls_new) + try: + mro_method = cls.py__mro__ + except AttributeError: + # TODO add a TypeError like: + """ + >>> class Y(lambda: test): pass + Traceback (most recent call last): + File "", line 1, in + TypeError: function() argument 1 must be code, not str + >>> class Y(1): pass + Traceback (most recent call last): + File "", line 1, in + TypeError: int() takes at most 2 arguments (3 given) + """ + pass + else: + add(cls) + for cls_new in mro_method(evaluator): + add(cls_new) return tuple(mro) @memoize_default(default=()) @@ -443,9 +459,16 @@ class Class(use_metaclass(CachedMetaClass, Wrapper)): def get_subscope_by_name(self, name): for s in [self] + self.py__bases__(self._evaluator): - for sub in reversed(s.subscopes): - if sub.name.value == name: - return sub + try: + subscopes = s.subscopes + except AttributeError: + # TODO look at the __mro__ todo, we should add a TypeError + # here. + pass + else: + for sub in reversed(subscopes): + if sub.name.value == name: + return sub raise KeyError("Couldn't find subscope.") def __getattr__(self, name): diff --git a/jedi/parser/fast.py b/jedi/parser/fast.py index acc224af..6cbf1737 100644 --- a/jedi/parser/fast.py +++ b/jedi/parser/fast.py @@ -174,7 +174,6 @@ class ParserNode(object): Closes the current parser node. This means that after this no further nodes should be added anymore. """ - #print('CLOSE NODE', id(self), self.parent, self._node_children) # We only need to replace the dict if multiple dictionaries are used: if self._node_children: dcts = [n.parser.module.names_dict for n in self._node_children] @@ -398,7 +397,6 @@ class FastParser(use_metaclass(CachedFastParser)): debug.dbg('While parsing %s, line %s slowed down the fast parser.', self.module_path, line_offset + 1) - print(line_offset, repr(code_part)) line_offset = next_line_offset start += len(code_part) diff --git a/test/completion/classes.py b/test/completion/classes.py index 82cbf99c..1481c6a9 100644 --- a/test/completion/classes.py +++ b/test/completion/classes.py @@ -450,9 +450,26 @@ class TestX(object): # ----------------- class A(object): - pass + a = 3 #? ['mro'] A.mro #? [] A().mro + + +# ----------------- +# mro resolution +# ----------------- + +class B(A()): + b = 3 + +#? +B.a +#? +B().a +#? int() +B.b +#? int() +B().b