From e23f453a11b901d5c9a711cd3c70919c27382be6 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Thu, 10 Dec 2015 01:48:08 +0100 Subject: [PATCH] Fix all remaining issues from the compiled refactoring except static analysis. --- jedi/api/__init__.py | 4 ++-- jedi/evaluate/compiled/__init__.py | 25 +++++++++++++++++++------ jedi/evaluate/iterable.py | 3 ++- test/test_evaluate/test_compiled.py | 26 ++++++++++++++------------ 4 files changed, 37 insertions(+), 21 deletions(-) diff --git a/jedi/api/__init__.py b/jedi/api/__init__.py index 9ddc7b7e..c5c105fc 100644 --- a/jedi/api/__init__.py +++ b/jedi/api/__init__.py @@ -12,7 +12,7 @@ import warnings import sys from itertools import chain -from jedi._compatibility import unicode +from jedi._compatibility import unicode, builtins from jedi.parser import Parser, load_grammar from jedi.parser.tokenize import source_tokens from jedi.parser import tree @@ -646,7 +646,7 @@ class Interpreter(Script): paths = path.split('.') if path else [] - namespaces = (NamespaceModule(), BUILTINS) + namespaces = (NamespaceModule(), builtins) for p in paths: old, namespaces = namespaces, [] for n in old: diff --git a/jedi/evaluate/compiled/__init__.py b/jedi/evaluate/compiled/__init__.py index 9ea7decf..dda185eb 100644 --- a/jedi/evaluate/compiled/__init__.py +++ b/jedi/evaluate/compiled/__init__.py @@ -200,18 +200,31 @@ class CompiledObject(Base): pass # self.obj maynot have an __iter__ method. return result + @property + def py__getitem__(self): + if not hasattr(self.obj, '__getitem__'): + raise AttributeError('No __getitem__ on %s' % self.obj) + + def actual(index): + if type(self.obj) not in (str, list, tuple, unicode, bytes, bytearray, dict): + # Get rid of side effects, we won't call custom `__getitem__`s. + return set() + + return set([create(self._evaluator, self.obj[index])]) + return actual + @property def py__iter__(self): if not hasattr(self.obj, '__iter__'): raise AttributeError('No __iter__ on %s' % self.obj) - def actual(evaluator): + def actual(): if type(self.obj) not in (str, list, tuple, unicode, bytes, bytearray, dict): # Get rid of side effects, we won't call custom `__getitem__`s. return for part in self.obj: - yield set([create(evaluator, part)]) + yield set([create(self._evaluator, part)]) return actual @property @@ -505,10 +518,7 @@ def get_special_object(evaluator, identifier): def compiled_objects_cache(func): def wrapper(evaluator, obj, parent=None, module=None): # Do a very cheap form of caching here. - if parent is None and not inspect.ismodule(obj): - parent = create(evaluator, _builtins) - - key = id(obj), id(parent), id(module) + key = id(obj) try: return evaluator.compiled_cache[key][0] except KeyError: @@ -525,6 +535,9 @@ def create(evaluator, obj, parent=None, module=None): A very weird interface class to this module. The more options provided the more acurate loading compiled objects is. """ + if parent is None and not inspect.ismodule(obj): + parent = create(evaluator, _builtins) + if not inspect.ismodule(obj): faked = fake.get_faked(module and module.obj, obj) if faked is not None: diff --git a/jedi/evaluate/iterable.py b/jedi/evaluate/iterable.py index 0e506862..cebe120d 100644 --- a/jedi/evaluate/iterable.py +++ b/jedi/evaluate/iterable.py @@ -404,7 +404,7 @@ class FakeSequence(_FakeArray): class AlreadyEvaluated(frozenset): """A simple container to add already evaluated objects to an array.""" - def get_code(self): + def get_code(self, normalized=False): # For debugging purposes. return str(self) @@ -523,6 +523,7 @@ def py__getitem__(evaluator, types, index, node): if isinstance(typ, Array) and typ.type == 'dict': types.remove(typ) result |= typ.dict_values() + print('ITER', types, py__iter__types(evaluator, types)) return result | py__iter__types(evaluator, types) for typ in types: diff --git a/test/test_evaluate/test_compiled.py b/test/test_evaluate/test_compiled.py index c0977a48..83ea5e56 100644 --- a/test/test_evaluate/test_compiled.py +++ b/test/test_evaluate/test_compiled.py @@ -6,10 +6,14 @@ from jedi.evaluate import Evaluator from jedi import Script +def _evaluator(): + return Evaluator(load_grammar()) + + def test_simple(): - e = Evaluator(load_grammar()) - bltn = compiled.CompiledObject(builtins) - obj = compiled.CompiledObject('_str_', bltn) + e = _evaluator() + bltn = compiled.CompiledObject(e, builtins) + obj = compiled.CompiledObject(e, '_str_', bltn) upper = e.find_types(obj, 'upper') assert len(upper) == 1 objs = list(e.execute(list(upper)[0])) @@ -18,19 +22,17 @@ def test_simple(): def test_fake_loading(): - assert isinstance(compiled.create(Evaluator(load_grammar()), next), Function) + e = _evaluator() + assert isinstance(compiled.create(e, next), Function) - string = compiled.builtin.get_subscope_by_name('str') - from_name = compiled._create_from_name( - compiled.builtin, - string, - '__init__' - ) + builtin = compiled.get_special_object(e, 'BUILTINS') + string = builtin.get_subscope_by_name('str') + from_name = compiled._create_from_name(e, builtin, string, '__init__') assert isinstance(from_name, Function) def test_fake_docstr(): - assert compiled.create(Evaluator(load_grammar()), next).raw_doc == next.__doc__ + assert compiled.create(_evaluator(), next).raw_doc == next.__doc__ def test_parse_function_doc_illegal_docstr(): @@ -47,7 +49,7 @@ def test_doc(): Even CompiledObject docs always return empty docstrings - not None, that's just a Jedi API definition. """ - obj = compiled.CompiledObject(''.__getnewargs__) + obj = compiled.CompiledObject(_evaluator(), ''.__getnewargs__) assert obj.doc == ''