1
0
forked from VimPlug/jedi

Changes for 3.8: sync_comp_for instead of comp_for

Please also look at the changes for parso in its b5d50392a4058919c0018666cdfc8c3eaaea9cb5 commit
This commit is contained in:
Dave Halter
2019-06-09 18:05:34 +02:00
parent f3364a458c
commit 42b6e20729
8 changed files with 48 additions and 25 deletions

View File

@@ -410,12 +410,12 @@ class Evaluator(object):
if parser_utils.is_scope(node): if parser_utils.is_scope(node):
return node return node
elif node.type in ('argument', 'testlist_comp'): elif node.type in ('argument', 'testlist_comp'):
if node.children[1].type == 'comp_for': if node.children[1].type in ('comp_for', 'sync_comp_for'):
return node.children[1] return node.children[1]
elif node.type == 'dictorsetmaker': elif node.type == 'dictorsetmaker':
for n in node.children[1:4]: for n in node.children[1:4]:
# In dictionaries it can be pretty much anything. # In dictionaries it can be pretty much anything.
if n.type == 'comp_for': if n.type in ('comp_for', 'sync_comp_for'):
return n return n
def from_scope_node(scope_node, is_nested=True, node_is_object=False): def from_scope_node(scope_node, is_nested=True, node_is_object=False):
@@ -441,7 +441,7 @@ class Evaluator(object):
return func return func
elif scope_node.type == 'classdef': elif scope_node.type == 'classdef':
return ClassContext(self, parent_context, scope_node) return ClassContext(self, parent_context, scope_node)
elif scope_node.type == 'comp_for': elif scope_node.type in ('comp_for', 'sync_comp_for'):
if node.start_pos >= scope_node.children[-1].start_pos: if node.start_pos >= scope_node.children[-1].start_pos:
return parent_context return parent_context
return CompForContext.from_comp_for(parent_context, scope_node) return CompForContext.from_comp_for(parent_context, scope_node)

View File

@@ -233,10 +233,13 @@ class TreeArguments(AbstractArguments):
named_args.append((c[0].value, LazyTreeContext(self.context, c[2]),)) named_args.append((c[0].value, LazyTreeContext(self.context, c[2]),))
else: # Generator comprehension. else: # Generator comprehension.
# Include the brackets with the parent. # Include the brackets with the parent.
sync_comp_for = el.children[1]
if sync_comp_for.type == 'comp_for':
sync_comp_for = sync_comp_for.children[1]
comp = iterable.GeneratorComprehension( comp = iterable.GeneratorComprehension(
self._evaluator, self._evaluator,
defining_context=self.context, defining_context=self.context,
comp_for_node=el.children[1], sync_comp_for_node=sync_comp_for,
entry_node=el.children[0], entry_node=el.children[0],
) )
yield None, LazyKnownContext(comp) yield None, LazyKnownContext(comp)

View File

@@ -8,7 +8,7 @@ just one.
""" """
from functools import reduce from functools import reduce
from operator import add from operator import add
from parso.python.tree import ExprStmt, CompFor from parso.python.tree import ExprStmt, SyncCompFor
from jedi import debug from jedi import debug
from jedi._compatibility import zip_longest, unicode from jedi._compatibility import zip_longest, unicode
@@ -330,7 +330,7 @@ class ContextualizedName(ContextualizedNode):
is_star_expr = False is_star_expr = False
elif node.type == 'star_expr': elif node.type == 'star_expr':
is_star_expr = True is_star_expr = True
elif isinstance(node, (ExprStmt, CompFor)): elif isinstance(node, (ExprStmt, SyncCompFor)):
break break
compare = node compare = node

View File

@@ -215,7 +215,7 @@ class AbstractInstanceContext(Context):
elif scope.type == 'classdef': elif scope.type == 'classdef':
class_context = ClassContext(self.evaluator, parent_context, scope) class_context = ClassContext(self.evaluator, parent_context, scope)
return class_context return class_context
elif scope.type == 'comp_for': elif scope.type in ('comp_for', 'sync_comp_for'):
# Comprehensions currently don't have a special scope in Jedi. # Comprehensions currently don't have a special scope in Jedi.
return self.create_instance_context(class_context, scope) return self.create_instance_context(class_context, scope)
else: else:

View File

@@ -38,7 +38,7 @@ from jedi.evaluate.filters import ParserTreeFilter, LazyAttributeOverwrite, \
publish_method publish_method
from jedi.evaluate.base_context import ContextSet, NO_CONTEXTS, \ from jedi.evaluate.base_context import ContextSet, NO_CONTEXTS, \
TreeContext, ContextualizedNode, iterate_contexts, HelperContextMixin TreeContext, ContextualizedNode, iterate_contexts, HelperContextMixin
from jedi.parser_utils import get_comp_fors from jedi.parser_utils import get_sync_comp_fors
class IterableMixin(object): class IterableMixin(object):
@@ -107,12 +107,17 @@ class CompForContext(TreeContext):
def comprehension_from_atom(evaluator, context, atom): def comprehension_from_atom(evaluator, context, atom):
bracket = atom.children[0] bracket = atom.children[0]
test_list_comp = atom.children[1] test_list_comp = atom.children[1]
if bracket == '{': if bracket == '{':
if atom.children[1].children[1] == ':': if atom.children[1].children[1] == ':':
sync_comp_for = test_list_comp.children[3]
if sync_comp_for.type == 'comp_for':
sync_comp_for = sync_comp_for.children[1]
return DictComprehension( return DictComprehension(
evaluator, evaluator,
context, context,
comp_for_node=test_list_comp.children[3], sync_comp_for_node=sync_comp_for,
key_node=test_list_comp.children[0], key_node=test_list_comp.children[0],
value_node=test_list_comp.children[2], value_node=test_list_comp.children[2],
) )
@@ -122,10 +127,15 @@ def comprehension_from_atom(evaluator, context, atom):
cls = GeneratorComprehension cls = GeneratorComprehension
elif bracket == '[': elif bracket == '[':
cls = ListComprehension cls = ListComprehension
sync_comp_for = test_list_comp.children[1]
if sync_comp_for.type == 'comp_for':
sync_comp_for = sync_comp_for.children[1]
return cls( return cls(
evaluator, evaluator,
defining_context=context, defining_context=context,
comp_for_node=test_list_comp.children[1], sync_comp_for_node=sync_comp_for,
entry_node=test_list_comp.children[0], entry_node=test_list_comp.children[0],
) )
@@ -138,16 +148,16 @@ class ComprehensionMixin(object):
def _nested(self, comp_fors, parent_context=None): def _nested(self, comp_fors, parent_context=None):
comp_for = comp_fors[0] comp_for = comp_fors[0]
is_async = 'async' == comp_for.children[comp_for.children.index('for') - 1] is_async = comp_for.parent.type == 'comp_for'
input_node = comp_for.children[comp_for.children.index('in') + 1] input_node = comp_for.children[3]
parent_context = parent_context or self._defining_context parent_context = parent_context or self._defining_context
input_types = parent_context.eval_node(input_node) input_types = parent_context.eval_node(input_node)
# TODO: simulate await if self.is_async # TODO: simulate await if self.is_async
cn = ContextualizedNode(parent_context, input_node) cn = ContextualizedNode(parent_context, input_node)
iterated = input_types.iterate(cn, is_async=is_async) iterated = input_types.iterate(cn, is_async=is_async)
exprlist = comp_for.children[comp_for.children.index('for') + 1] exprlist = comp_for.children[1]
for i, lazy_context in enumerate(iterated): for i, lazy_context in enumerate(iterated):
types = lazy_context.infer() types = lazy_context.infer()
dct = unpack_tuple_to_dict(parent_context, types, exprlist) dct = unpack_tuple_to_dict(parent_context, types, exprlist)
@@ -169,7 +179,7 @@ class ComprehensionMixin(object):
@evaluator_method_cache(default=[]) @evaluator_method_cache(default=[])
@to_list @to_list
def _iterate(self): def _iterate(self):
comp_fors = tuple(get_comp_fors(self._comp_for_node)) comp_fors = tuple(get_sync_comp_fors(self._sync_comp_for_node))
for result in self._nested(comp_fors): for result in self._nested(comp_fors):
yield result yield result
@@ -178,7 +188,7 @@ class ComprehensionMixin(object):
yield LazyKnownContexts(set_) yield LazyKnownContexts(set_)
def __repr__(self): def __repr__(self):
return "<%s of %s>" % (type(self).__name__, self._comp_for_node) return "<%s of %s>" % (type(self).__name__, self._sync_comp_for_node)
class _DictMixin(object): class _DictMixin(object):
@@ -219,10 +229,11 @@ class Sequence(LazyAttributeOverwrite, IterableMixin):
class _BaseComprehension(ComprehensionMixin): class _BaseComprehension(ComprehensionMixin):
def __init__(self, evaluator, defining_context, comp_for_node, entry_node): def __init__(self, evaluator, defining_context, sync_comp_for_node, entry_node):
assert sync_comp_for_node.type == 'sync_comp_for'
super(_BaseComprehension, self).__init__(evaluator) super(_BaseComprehension, self).__init__(evaluator)
self._defining_context = defining_context self._defining_context = defining_context
self._comp_for_node = comp_for_node self._sync_comp_for_node = sync_comp_for_node
self._entry_node = entry_node self._entry_node = entry_node
@@ -250,10 +261,11 @@ class GeneratorComprehension(_BaseComprehension, GeneratorBase):
class DictComprehension(ComprehensionMixin, Sequence): class DictComprehension(ComprehensionMixin, Sequence):
array_type = u'dict' array_type = u'dict'
def __init__(self, evaluator, defining_context, comp_for_node, key_node, value_node): def __init__(self, evaluator, defining_context, sync_comp_for_node, key_node, value_node):
assert sync_comp_for_node.type == 'sync_comp_for'
super(DictComprehension, self).__init__(evaluator) super(DictComprehension, self).__init__(evaluator)
self._defining_context = defining_context self._defining_context = defining_context
self._comp_for_node = comp_for_node self._sync_comp_for_node = sync_comp_for_node
self._entry_node = key_node self._entry_node = key_node
self._value_node = value_node self._value_node = value_node

View File

@@ -134,11 +134,12 @@ class NameFinder(object):
``filters``), until a name fits. ``filters``), until a name fits.
""" """
names = [] names = []
# TODO why is this paragraph needed?
if self._context.predefined_names and isinstance(self._name, tree.Name): if self._context.predefined_names and isinstance(self._name, tree.Name):
node = self._name node = self._name
while node is not None and not is_scope(node): while node is not None and not is_scope(node):
node = node.parent node = node.parent
if node.type in ("if_stmt", "for_stmt", "comp_for"): if node.type in ("if_stmt", "for_stmt", "comp_for", 'sync_comp_for'):
try: try:
name_dict = self._context.predefined_names[node] name_dict = self._context.predefined_names[node]
types = name_dict[self._string_name] types = name_dict[self._string_name]
@@ -199,7 +200,7 @@ class NameFinder(object):
flow_scope = self._name flow_scope = self._name
base_nodes = [self._name_context.tree_node] base_nodes = [self._name_context.tree_node]
if any(b.type == 'comp_for' for b in base_nodes): if any(b.type in ('comp_for', 'sync_comp_for') for b in base_nodes):
return contexts return contexts
while True: while True:
flow_scope = get_parent_scope(flow_scope, include_flows=True) flow_scope = get_parent_scope(flow_scope, include_flows=True)

View File

@@ -247,7 +247,7 @@ def eval_atom(context, atom):
except IndexError: except IndexError:
pass pass
if comp_for.type == 'comp_for': if comp_for.type in ('comp_for', 'sync_comp_for'):
return ContextSet([iterable.comprehension_from_atom( return ContextSet([iterable.comprehension_from_atom(
context.evaluator, context, atom context.evaluator, context, atom
)]) )])
@@ -588,7 +588,7 @@ def tree_name_to_contexts(evaluator, context, tree_name):
if types: if types:
return types return types
if typ in ('for_stmt', 'comp_for'): if typ in ('for_stmt', 'comp_for', 'sync_comp_for'):
try: try:
types = context.predefined_names[node][tree_name.value] types = context.predefined_names[node][tree_name.value]
except KeyError: except KeyError:

View File

@@ -54,11 +54,13 @@ def get_executable_nodes(node, last_added=False):
return result return result
def get_comp_fors(comp_for): def get_sync_comp_fors(comp_for):
yield comp_for yield comp_for
last = comp_for.children[-1] last = comp_for.children[-1]
while True: while True:
if last.type == 'comp_for': if last.type == 'comp_for':
yield last.children[1] # Ignore the async.
elif last.type == 'sync_comp_for':
yield last yield last
elif not last.type == 'comp_if': elif not last.type == 'comp_if':
break break
@@ -216,7 +218,12 @@ def get_following_comment_same_line(node):
def is_scope(node): def is_scope(node):
return node.type in ('file_input', 'classdef', 'funcdef', 'lambdef', 'comp_for') t = node.type
if t == 'comp_for':
# Starting with Python 3.8, async is outside of the statement.
return node.children[1].type != 'sync_comp_for'
return t in ('file_input', 'classdef', 'funcdef', 'lambdef', 'sync_comp_for')
def get_parent_scope(node, include_flows=False): def get_parent_scope(node, include_flows=False):