From da1a163da70d0b1b52c1b5881dd536410c93dde6 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Sat, 3 Dec 2016 02:08:40 +0100 Subject: [PATCH] Fix python 2 string iterators. --- jedi/evaluate/compiled/__init__.py | 12 +++++++++++- jedi/evaluate/compiled/fake/builtins.pym | 5 +++++ jedi/evaluate/iterable.py | 3 ++- test/completion/comprehensions.py | 3 +++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/jedi/evaluate/compiled/__init__.py b/jedi/evaluate/compiled/__init__.py index 95214fa4..66d17840 100644 --- a/jedi/evaluate/compiled/__init__.py +++ b/jedi/evaluate/compiled/__init__.py @@ -33,7 +33,17 @@ class CheckAttribute(object): def __get__(self, instance, owner): # This might raise an AttributeError. That's wanted. - getattr(instance.obj, self.check_name) + if self.check_name == '__iter__': + # Python iterators are a bit strange, because there's no need for + # the __iter__ function as long as __getitem__ is defined (it will + # just start with __getitem__(0). This is especially true for + # Python 2 strings, where `str.__iter__` is not even defined. + try: + iter(instance.obj) + except TypeError: + raise AttributeError + else: + getattr(instance.obj, self.check_name) return partial(self.func, instance) diff --git a/jedi/evaluate/compiled/fake/builtins.pym b/jedi/evaluate/compiled/fake/builtins.pym index 1d5314bd..2fc50ce1 100644 --- a/jedi/evaluate/compiled/fake/builtins.pym +++ b/jedi/evaluate/compiled/fake/builtins.pym @@ -256,6 +256,11 @@ class str(): def __init__(self, obj): pass + def strip(self): + return str() + + def split(self): + return [str()] class type(): def mro(): diff --git a/jedi/evaluate/iterable.py b/jedi/evaluate/iterable.py index 1890905a..ebc6645d 100644 --- a/jedi/evaluate/iterable.py +++ b/jedi/evaluate/iterable.py @@ -237,7 +237,8 @@ class Comprehension(AbstractSequence): @memoize_default() def _get_comp_for_context(self, parent_context, comp_for): - return parent_context.create_context(comp_for) + # TODO shouldn't this be part of create_context? + return CompForContext.from_comp_for(parent_context, comp_for) def _nested(self, comp_fors, parent_context=None): evaluator = self.evaluator diff --git a/test/completion/comprehensions.py b/test/completion/comprehensions.py index 4f500b6c..610cc3d3 100644 --- a/test/completion/comprehensions.py +++ b/test/completion/comprehensions.py @@ -89,6 +89,9 @@ b = [b for arr in [[[1.0]]] for a in arr for b in a] #? float() b[0] +#? str() +[x for x in 'chr'][0] + # jedi issue #26 #? list() a = [[int(v) for v in line.strip().split() if v] for line in ["123", "123", "123"] if line]