Replace a lot more of empty sets and unite calls.

This commit is contained in:
Dave Halter
2017-09-25 23:08:59 +02:00
parent 921d1008f2
commit 174eff5875
14 changed files with 72 additions and 66 deletions

View File

@@ -35,6 +35,9 @@ class ContextSet(object):
def __bool__(self):
return bool(self._set)
def __len__(self):
return len(self._set)
def __repr__(self):
return '%s(%s)' % (self.__class__.__name__, ', '.join(str(s) for s in self._set))

View File

@@ -433,7 +433,7 @@ class Evaluator(object):
node = ()
if trailer_op == '[':
return ContextSet(iterable.py__getitem__(self, context, types, trailer))
return iterable.py__getitem__(self, context, types, trailer)
else:
context_set = ContextSet()
for typ in types:

View File

@@ -223,7 +223,10 @@ def _execute_types_in_stmt(module_context, stmt):
contain is executed. (Used as type information).
"""
definitions = module_context.eval_node(stmt)
return unite(_execute_array_values(module_context.evaluator, d) for d in definitions)
return ContextSet.from_sets(
_execute_array_values(module_context.evaluator, d)
for d in definitions
)
def _execute_array_values(evaluator, array):
@@ -234,7 +237,10 @@ def _execute_array_values(evaluator, array):
if isinstance(array, SequenceLiteralContext):
values = []
for lazy_context in array.py__iter__():
objects = unite(_execute_array_values(evaluator, typ) for typ in lazy_context.infer())
objects = ContextSet.from_sets(
_execute_array_values(evaluator, typ)
for typ in lazy_context.infer()
)
values.append(context.LazyKnownContexts(objects))
return set([FakeSequence(evaluator, array.array_type, values)])
else:

View File

@@ -24,7 +24,8 @@ from jedi.evaluate.cache import evaluator_function_cache
from jedi.evaluate import imports
from jedi.evaluate.param import TreeArguments, create_default_params
from jedi.evaluate.helpers import is_stdlib_path
from jedi.evaluate.utils import to_list, unite
from jedi.evaluate.utils import to_list
from jedi.common import ContextSet
from jedi.parser_utils import get_parent_scope
@@ -50,7 +51,7 @@ class MergedExecutedParams(object):
self._executed_params = executed_params
def infer(self):
return unite(p.infer() for p in self._executed_params)
return ContextSet.from_sets(p.infer() for p in self._executed_params)
@debug.increase_indent
@@ -103,7 +104,7 @@ def search_params(evaluator, execution_context, funcdef):
evaluator.dynamic_params_depth -= 1
@evaluator_function_cache(default=[])
@evaluator_function_cache(default=None)
@to_list
def _search_function_executions(evaluator, module_context, funcdef):
"""

View File

@@ -6,9 +6,9 @@ from abc import abstractmethod
from parso.tree import search_ancestor
from jedi.evaluate import flow_analysis
from jedi.evaluate.utils import to_list, unite
from jedi.common import ContextSet
from jedi.parser_utils import get_parent_scope
from jedi.evaluate.utils import to_list
class AbstractNameDefinition(object):
@@ -36,10 +36,10 @@ class AbstractNameDefinition(object):
return '<%s: %s@%s>' % (self.__class__.__name__, self.string_name, self.start_pos)
def execute(self, arguments):
return unite(context.execute(arguments) for context in self.infer())
return self.infer().execute(arguments)
def execute_evaluated(self, *args, **kwargs):
return unite(context.execute_evaluated(*args, **kwargs) for context in self.infer())
return self.infer().execute_evaluated(*args, **kwargs)
@property
def api_type(self):

View File

@@ -233,10 +233,7 @@ def _name_to_types(evaluator, context, tree_name):
# TODO check for types that are not classes and add it to
# the static analysis report.
exceptions = context.eval_node(tree_name.get_previous_sibling().get_previous_sibling())
types = unite(
evaluator.execute(t, param.ValuesArguments([]))
for t in exceptions
)
types = exceptions.execute_evaluated()
else:
raise ValueError("Should not happen.")
return types
@@ -274,8 +271,7 @@ def _apply_decorators(evaluator, context, node):
debug.warning('decorator not found: %s on %s', dec, node)
return initial
values = unite(dec_value.execute(param.ValuesArguments([values]))
for dec_value in dec_values)
values = dec_values.execute(param.ValuesArguments([values]))
if not len(values):
debug.warning('not possible to resolve wrappers found %s', node)
return initial

View File

@@ -24,7 +24,6 @@ from parso import python_bytes_to_unicode
from jedi._compatibility import find_module, unicode, ImplicitNSInfo
from jedi import debug
from jedi import settings
from jedi.evaluate.utils import unite
from jedi.evaluate import sys_path
from jedi.evaluate import helpers
from jedi.evaluate import compiled
@@ -67,13 +66,11 @@ def infer_import(context, tree_name, is_goto=False):
return NO_CONTEXTS
if from_import_name is not None:
types = unite(
t.py__getattribute__(
from_import_name,
name_context=context,
is_goto=is_goto,
analysis_errors=False
) for t in types
types = types.py__getattribute__(
from_import_name,
name_context=context,
is_goto=is_goto,
analysis_errors=False
)
if not types:

View File

@@ -1,7 +1,6 @@
from abc import abstractproperty
from jedi._compatibility import is_py3
from jedi.evaluate.utils import unite
from jedi import debug
from jedi.evaluate import compiled
from jedi.evaluate import filters
@@ -11,7 +10,7 @@ from jedi.evaluate.param import AbstractArguments, AnonymousArguments
from jedi.cache import memoize_method
from jedi.evaluate import representation as er
from jedi.evaluate import iterable
from jedi.common import ContextSet, iterator_to_context_set
from jedi.common import ContextSet, iterator_to_context_set, NO_CONTEXTS
from jedi.parser_utils import get_parent_scope
@@ -59,7 +58,7 @@ class AbstractInstanceContext(Context):
raise AttributeError
def execute(arguments):
return unite(name.execute(arguments) for name in names)
return ContextSet.from_sets(name.execute(arguments) for name in names)
return execute
@@ -81,7 +80,7 @@ class AbstractInstanceContext(Context):
return []
def execute_function_slots(self, names, *evaluated_args):
return unite(
return ContextSet.from_sets(
name.execute_evaluated(*evaluated_args)
for name in names
)
@@ -97,7 +96,7 @@ class AbstractInstanceContext(Context):
none_obj = compiled.create(self.evaluator, None)
return self.execute_function_slots(names, none_obj, obj)
else:
return set([self])
return ContextSet(self)
def get_filters(self, search_global=None, until_position=None,
origin_scope=None, include_self_names=True):
@@ -123,7 +122,7 @@ class AbstractInstanceContext(Context):
names = self.get_function_slot_names('__getitem__')
except KeyError:
debug.warning('No __getitem__, cannot access the array.')
return set()
return NO_CONTEXTS
else:
index_obj = compiled.create(self.evaluator, index)
return self.execute_function_slots(names, index_obj)

View File

@@ -144,7 +144,7 @@ class GeneratorMixin(object):
@register_builtin_method('__next__', python_version_match=3)
def py__next__(self):
# TODO add TypeError if params are given.
return unite(lazy_context.infer() for lazy_context in self.py__iter__())
return ContextSet.from_sets(lazy_context.infer() for lazy_context in self.py__iter__())
def get_filters(self, search_global, until_position=None, origin_scope=None):
gen_obj = compiled.get_special_object(self.evaluator, 'GENERATOR_OBJECT')
@@ -297,7 +297,8 @@ class ArrayMixin(object):
return self.evaluator.BUILTINS
def dict_values(self):
return unite(self._defining_context.eval_node(v) for k, v in self._items())
return ContextSet.from_sets(self._defining_context.eval_node(v)
for k, v in self._items())
class ListComprehension(ArrayMixin, Comprehension):
@@ -335,7 +336,7 @@ class DictComprehension(ArrayMixin, Comprehension):
return self.dict_values()
def dict_values(self):
return unite(values for keys, values in self._iterate())
return ContextSet.from_sets(values for keys, values in self._iterate())
@register_builtin_method('values')
def _imitate_values(self):
@@ -414,7 +415,7 @@ class SequenceLiteralContext(ArrayMixin, AbstractSequence):
def _values(self):
"""Returns a list of a list of node."""
if self.array_type == 'dict':
return unite(v for k, v in self._items())
return ContextSet.from_sets(v for k, v in self._items())
else:
return self._items()
@@ -532,7 +533,7 @@ class FakeDict(_FakeArray):
return self._dct[index].infer()
def dict_values(self):
return unite(lazy_context.infer() for lazy_context in self._dct.values())
return ContextSet.from_sets(lazy_context.infer() for lazy_context in self._dct.values())
def _items(self):
raise DeprecationWarning
@@ -555,7 +556,7 @@ class MergedArray(_FakeArray):
yield lazy_context
def py__getitem__(self, index):
return unite(lazy_context.infer() for lazy_context in self.py__iter__())
return ContextSet.from_sets(lazy_context.infer() for lazy_context in self.py__iter__())
def _items(self):
for array in self._arrays:
@@ -633,7 +634,7 @@ def py__iter__types(evaluator, types, contextualized_node=None):
Calls `py__iter__`, but ignores the ordering in the end and just returns
all types that it contains.
"""
return unite(
return ContextSet.from_sets(
lazy_context.infer()
for lazy_context in py__iter__(evaluator, types, contextualized_node)
)
@@ -740,7 +741,7 @@ def _check_array_additions(context, sequence):
is_list = sequence.name.string_name == 'list'
search_names = (['append', 'extend', 'insert'] if is_list else ['add', 'update'])
added_types = NO_CONTEXTS()
added_types = NO_CONTEXTS
for add_name in search_names:
try:
possible_names = module_context.tree_node.get_used_names()[add_name]

View File

@@ -10,6 +10,7 @@ from jedi.evaluate import context
from jedi.evaluate import docstrings
from jedi.evaluate import pep0484
from jedi.evaluate.filters import ParamName
from jedi.common import NO_CONTEXTS
def add_argument_issue(parent_context, error_name, lazy_context, message):
@@ -51,7 +52,7 @@ class AbstractArguments():
debug.warning('TypeError: %s expected at least %s arguments, got %s',
name, len(parameters), i)
raise ValueError
values = set() if argument is None else argument.infer()
values = NO_CONTEXTS if argument is None else argument.infer()
if not values and not optional:
# For the stdlib we always want values. If we don't get them,

View File

@@ -25,11 +25,10 @@ import re
from parso import ParserSyntaxError
from parso.python import tree
from jedi.evaluate.utils import unite
from jedi.evaluate.cache import evaluator_method_cache
from jedi.evaluate import compiled
from jedi.evaluate.context import LazyTreeContext
from jedi.common import NO_CONTEXTS
from jedi.common import NO_CONTEXTS, ContextSet
from jedi import debug
from jedi import _compatibility
from jedi import parser_utils
@@ -146,7 +145,7 @@ def py__getitem__(context, typ, node):
if type_name in ("Union", '_Union'):
# In Python 3.6 it's still called typing.Union but it's an instance
# called _Union.
return unite(context.eval_node(node) for node in nodes)
return ContextSet.from_sets(context.eval_node(node) for node in nodes)
if type_name in ("Optional", '_Optional'):
# Here we have the same issue like in Union. Therefore we also need to
# check for the instance typing._Optional (Python 3.6).

View File

@@ -7,7 +7,7 @@ from jedi._compatibility import unicode
from jedi import debug
from jedi.evaluate.compiled import CompiledObject, create, builtin_from_name
from jedi.evaluate import analysis
from jedi.common import ContextSet
from jedi.common import ContextSet, NO_CONTEXTS
# Maps Python syntax to the operator module.
COMPARISON_OPERATORS = {
@@ -162,7 +162,7 @@ def _element_calculate(evaluator, context, left, operator, right):
else:
return ContextSet(create(evaluator, result))
elif operator == 'in':
return set()
return NO_CONTEXTS
def check(obj):
"""Checks if a Jedi object is either a float or an int."""

View File

@@ -29,6 +29,7 @@ therefore the quality might not always be maximal.
from contextlib import contextmanager
from jedi import debug
from jedi.common import NO_CONTEXTS
recursion_limit = 15
@@ -71,7 +72,7 @@ def execution_allowed(evaluator, node):
pushed_nodes.pop()
def execution_recursion_decorator(default=set()):
def execution_recursion_decorator(default=NO_CONTEXTS):
def decorator(func):
def wrapper(execution, **kwargs):
detector = execution.evaluator.execution_recursion_detector

View File

@@ -24,6 +24,7 @@ from jedi.evaluate import precedence
from jedi.evaluate import param
from jedi.evaluate import analysis
from jedi.evaluate.context import LazyTreeContext, ContextualizedNode
from jedi.common import NO_CONTEXTS, ContextSet
# Now this is all part of fake tuples in Jedi. However super doesn't work on
# __init__ and __new__ doesn't work at all. So adding this to nametuples is
@@ -77,7 +78,7 @@ def _follow_param(evaluator, arguments, index):
try:
key, lazy_context = list(arguments.unpack())[index]
except IndexError:
return set()
return NO_CONTEXTS
else:
return lazy_context.infer()
@@ -109,7 +110,7 @@ def argument_clinic(string, want_obj=False, want_context=False, want_arguments=F
try:
lst = list(arguments.eval_argument_clinic(clinic_args))
except ValueError:
return set()
return NO_CONTEXTS
else:
kwargs = {}
if want_context:
@@ -137,15 +138,16 @@ def builtins_next(evaluator, iterators, defaults):
else:
name = '__next__'
types = set()
context_set = NO_CONTEXTS
for iterator in iterators:
if isinstance(iterator, AbstractInstanceContext):
for filter in iterator.get_filters(include_self_names=True):
for n in filter.get(name):
for context in n.infer():
types |= context.execute_evaluated()
if types:
return types
context_set = ContextSet.from_sets(
n.infer()
for filter in iterator.get_filters(include_self_names=True)
for n in filter.get(name)
).execute_evaluated()
if context_set:
return context_set
return defaults
@@ -159,16 +161,16 @@ def builtins_getattr(evaluator, objects, names, defaults=None):
else:
debug.warning('getattr called without str')
continue
return set()
return NO_CONTEXTS
@argument_clinic('object[, bases, dict], /')
def builtins_type(evaluator, objects, bases, dicts):
if bases or dicts:
# It's a type creation... maybe someday...
return set()
return NO_CONTEXTS
else:
return set([o.py__class__() for o in objects])
return ContextSet.from_iterable(o.py__class__() for o in objects)
class SuperInstance(AbstractInstanceContext):
@@ -185,7 +187,7 @@ def builtins_super(evaluator, types, objects, context):
AnonymousInstanceFunctionExecution)):
su = context.instance.py__class__().py__bases__()
return unite(context.execute_evaluated() for context in su[0].infer())
return set()
return NO_CONTEXTS
@argument_clinic('sequence, /', want_obj=True, want_arguments=True)
@@ -207,12 +209,12 @@ def builtins_reversed(evaluator, sequences, obj, arguments):
# just returned the result directly.
seq = iterable.FakeSequence(evaluator, 'list', rev)
arguments = param.ValuesArguments([[seq]])
return set([CompiledInstance(evaluator, evaluator.BUILTINS, obj, arguments)])
return ContextSet(CompiledInstance(evaluator, evaluator.BUILTINS, obj, arguments))
@argument_clinic('obj, type, /', want_arguments=True)
def builtins_isinstance(evaluator, objects, types, arguments):
bool_results = set([])
bool_results = set()
for o in objects:
try:
mro_func = o.py__class__().py__mro__
@@ -220,7 +222,7 @@ def builtins_isinstance(evaluator, objects, types, arguments):
# This is temporary. Everything should have a class attribute in
# Python?! Maybe we'll leave it here, because some numpy objects or
# whatever might not.
return set([compiled.create(True), compiled.create(False)])
return ContextSet(compiled.create(True), compiled.create(False))
mro = mro_func()
@@ -244,7 +246,7 @@ def builtins_isinstance(evaluator, objects, types, arguments):
'not %s.' % cls_or_tup
analysis.add(lazy_context._context, 'type-error-isinstance', node, message)
return set(compiled.create(evaluator, x) for x in bool_results)
return ContextSet.from_iterable(compiled.create(evaluator, x) for x in bool_results)
def collections_namedtuple(evaluator, obj, arguments):
@@ -259,7 +261,7 @@ def collections_namedtuple(evaluator, obj, arguments):
"""
# Namedtuples are not supported on Python 2.6
if not hasattr(collections, '_class_template'):
return set()
return NO_CONTEXTS
# Process arguments
# TODO here we only use one of the types, we should use all.
@@ -274,7 +276,7 @@ def collections_namedtuple(evaluator, obj, arguments):
for v in lazy_context.infer() if hasattr(v, 'obj')
]
else:
return set()
return NO_CONTEXTS
base = collections._class_template
base += _NAMEDTUPLE_INIT
@@ -293,7 +295,7 @@ def collections_namedtuple(evaluator, obj, arguments):
module = evaluator.grammar.parse(source)
generated_class = next(module.iter_classdefs())
parent_context = er.ModuleContext(evaluator, module, '')
return set([er.ClassContext(evaluator, generated_class, parent_context)])
return ContextSet(er.ClassContext(evaluator, generated_class, parent_context))
@argument_clinic('first, /')
@@ -314,8 +316,8 @@ _implemented = {
'deepcopy': _return_first_param,
},
'json': {
'load': lambda *args: set(),
'loads': lambda *args: set(),
'load': lambda *args: NO_CONTEXTS,
'loads': lambda *args: NO_CONTEXTS,
},
'collections': {
'namedtuple': collections_namedtuple,