mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-22 13:21:26 +08:00
Function for evaluating functions with already executed arguments.
This commit is contained in:
@@ -256,6 +256,13 @@ class Evaluator(object):
|
|||||||
new_types += get(self, node)
|
new_types += get(self, node)
|
||||||
return new_types
|
return new_types
|
||||||
|
|
||||||
|
def execute_evaluated(self, obj, *args):
|
||||||
|
"""
|
||||||
|
Execute a function with already executed arguments.
|
||||||
|
"""
|
||||||
|
args = [iterable.AlreadyEvaluated([arg]) for arg in args]
|
||||||
|
return self.execute(obj, args)
|
||||||
|
|
||||||
@debug.increase_indent
|
@debug.increase_indent
|
||||||
def execute(self, obj, arguments=(), trailer=None):
|
def execute(self, obj, arguments=(), trailer=None):
|
||||||
if not isinstance(arguments, param.Arguments):
|
if not isinstance(arguments, param.Arguments):
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ It works as follows:
|
|||||||
from jedi._compatibility import unicode
|
from jedi._compatibility import unicode
|
||||||
from jedi.parser import representation as pr
|
from jedi.parser import representation as pr
|
||||||
from jedi import settings
|
from jedi import settings
|
||||||
|
from jedi import debug
|
||||||
from jedi.evaluate import helpers
|
from jedi.evaluate import helpers
|
||||||
from jedi.evaluate.cache import memoize_default
|
from jedi.evaluate.cache import memoize_default
|
||||||
from jedi.evaluate import imports
|
from jedi.evaluate import imports
|
||||||
@@ -40,6 +41,7 @@ class ParamListener(object):
|
|||||||
self.param_possibilities.append(params)
|
self.param_possibilities.append(params)
|
||||||
|
|
||||||
|
|
||||||
|
@debug.increase_indent
|
||||||
@memoize_default([], evaluator_is_first_arg=True)
|
@memoize_default([], evaluator_is_first_arg=True)
|
||||||
def search_params(evaluator, param):
|
def search_params(evaluator, param):
|
||||||
"""
|
"""
|
||||||
@@ -57,6 +59,7 @@ def search_params(evaluator, param):
|
|||||||
if not settings.dynamic_params:
|
if not settings.dynamic_params:
|
||||||
return []
|
return []
|
||||||
from jedi.evaluate import representation as er
|
from jedi.evaluate import representation as er
|
||||||
|
debug.dbg('Dynamic param search for %s', param)
|
||||||
|
|
||||||
def get_params_for_module(module):
|
def get_params_for_module(module):
|
||||||
"""
|
"""
|
||||||
@@ -71,7 +74,7 @@ def search_params(evaluator, param):
|
|||||||
|
|
||||||
for name in names:
|
for name in names:
|
||||||
stmt = name.get_definition()
|
stmt = name.get_definition()
|
||||||
if not isinstance(stmt, (pr.ExprStmt, pr.CompFor)):
|
if not isinstance(stmt, (pr.ExprStmt, pr.CompFor, pr.ReturnStmt)):
|
||||||
continue
|
continue
|
||||||
parent = name.parent
|
parent = name.parent
|
||||||
if pr.is_node(parent, 'trailer'):
|
if pr.is_node(parent, 'trailer'):
|
||||||
@@ -179,4 +182,5 @@ def search_params(evaluator, param):
|
|||||||
# cleanup: remove the listener; important: should not stick.
|
# cleanup: remove the listener; important: should not stick.
|
||||||
func.listeners.remove(listener)
|
func.listeners.remove(listener)
|
||||||
|
|
||||||
|
debug.dbg('Dynamic param result %s', result)
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -211,14 +211,14 @@ class NameFinder(object):
|
|||||||
# str is important, because it shouldn't be `Name`!
|
# str is important, because it shouldn't be `Name`!
|
||||||
name = compiled.create(self._evaluator, str(self.name_str))
|
name = compiled.create(self._evaluator, str(self.name_str))
|
||||||
with common.ignored(KeyError):
|
with common.ignored(KeyError):
|
||||||
result = inst.execute_subscope_by_name('__getattr__', [name])
|
result = inst.execute_subscope_by_name('__getattr__', name)
|
||||||
if not result:
|
if not result:
|
||||||
# this is a little bit special. `__getattribute__` is executed
|
# this is a little bit special. `__getattribute__` is executed
|
||||||
# before anything else. But: I know no use case, where this
|
# before anything else. But: I know no use case, where this
|
||||||
# could be practical and the jedi would return wrong types. If
|
# could be practical and the jedi would return wrong types. If
|
||||||
# you ever have something, let me know!
|
# you ever have something, let me know!
|
||||||
with common.ignored(KeyError):
|
with common.ignored(KeyError):
|
||||||
result = inst.execute_subscope_by_name('__getattribute__', [name])
|
result = inst.execute_subscope_by_name('__getattribute__', name)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def _is_name_break_scope(self, stmt):
|
def _is_name_break_scope(self, stmt):
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ def get_params(evaluator, func, var_args):
|
|||||||
from jedi.evaluate.representation import InstanceElement
|
from jedi.evaluate.representation import InstanceElement
|
||||||
if isinstance(func, InstanceElement):
|
if isinstance(func, InstanceElement):
|
||||||
# Include self at this place.
|
# Include self at this place.
|
||||||
unpacked_va.insert(0, (None, [func.instance]))
|
unpacked_va.insert(0, (None, [iterable.AlreadyEvaluated([func.instance])]))
|
||||||
var_arg_iterator = common.PushBackIterator(iter(unpacked_va))
|
var_arg_iterator = common.PushBackIterator(iter(unpacked_va))
|
||||||
|
|
||||||
non_matching_keys = defaultdict(lambda: [])
|
non_matching_keys = defaultdict(lambda: [])
|
||||||
@@ -289,6 +289,7 @@ def get_params(evaluator, func, var_args):
|
|||||||
result.append(_gen_param_name_copy(evaluator, func, var_args,
|
result.append(_gen_param_name_copy(evaluator, func, var_args,
|
||||||
param, [], values))
|
param, [], values))
|
||||||
|
|
||||||
|
|
||||||
if not (non_matching_keys or had_multiple_value_error
|
if not (non_matching_keys or had_multiple_value_error
|
||||||
or param.stars or param.default):
|
or param.stars or param.default):
|
||||||
# add a warning only if there's not another one.
|
# add a warning only if there's not another one.
|
||||||
|
|||||||
@@ -97,8 +97,12 @@ class Instance(use_metaclass(CachedMetaClass, Executed)):
|
|||||||
else:
|
else:
|
||||||
# Need to execute the __init__ function, because the dynamic param
|
# Need to execute the __init__ function, because the dynamic param
|
||||||
# searching needs it.
|
# searching needs it.
|
||||||
with common.ignored(KeyError):
|
try:
|
||||||
self.execute_subscope_by_name('__init__', self.var_args)
|
method = self.get_subscope_by_name('__init__')
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
evaluator.execute(method, self.var_args)
|
||||||
# Generated instances are classes that are just generated by self
|
# Generated instances are classes that are just generated by self
|
||||||
# (No var_args) used.
|
# (No var_args) used.
|
||||||
self.is_generated = is_generated
|
self.is_generated = is_generated
|
||||||
@@ -180,16 +184,16 @@ class Instance(use_metaclass(CachedMetaClass, Executed)):
|
|||||||
sub = self.base.get_subscope_by_name(name)
|
sub = self.base.get_subscope_by_name(name)
|
||||||
return get_instance_el(self._evaluator, self, sub, True)
|
return get_instance_el(self._evaluator, self, sub, True)
|
||||||
|
|
||||||
def execute_subscope_by_name(self, name, args=()):
|
def execute_subscope_by_name(self, name, *args):
|
||||||
method = self.get_subscope_by_name(name)
|
method = self.get_subscope_by_name(name)
|
||||||
return self._evaluator.execute(method, args)
|
return self._evaluator.execute_evaluated(method, *args)
|
||||||
|
|
||||||
def get_descriptor_return(self, obj):
|
def get_descriptor_return(self, obj):
|
||||||
""" Throws a KeyError if there's no method. """
|
""" Throws a KeyError if there's no method. """
|
||||||
# Arguments in __get__ descriptors are obj, class.
|
# Arguments in __get__ descriptors are obj, class.
|
||||||
# `method` is the new parent of the array, don't know if that's good.
|
# `method` is the new parent of the array, don't know if that's good.
|
||||||
args = [obj, obj.base] if isinstance(obj, Instance) else [compiled.none_obj, obj]
|
args = [obj, obj.base] if isinstance(obj, Instance) else [compiled.none_obj, obj]
|
||||||
return self.execute_subscope_by_name('__get__', args)
|
return self.execute_subscope_by_name('__get__', *args)
|
||||||
|
|
||||||
def scope_names_generator(self, position=None):
|
def scope_names_generator(self, position=None):
|
||||||
"""
|
"""
|
||||||
@@ -211,7 +215,7 @@ class Instance(use_metaclass(CachedMetaClass, Executed)):
|
|||||||
indexes = []
|
indexes = []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return self.execute_subscope_by_name('__getitem__', [indexes])
|
return self.execute_subscope_by_name('__getitem__', indexes)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
debug.warning('No __getitem__, cannot access the array.')
|
debug.warning('No __getitem__, cannot access the array.')
|
||||||
return []
|
return []
|
||||||
@@ -494,8 +498,7 @@ class Function(use_metaclass(CachedMetaClass, Wrapper)):
|
|||||||
# Create param array.
|
# Create param array.
|
||||||
old_func = Function(self._evaluator, f, is_decorated=True)
|
old_func = Function(self._evaluator, f, is_decorated=True)
|
||||||
|
|
||||||
arg = iterable.AlreadyEvaluated([old_func])
|
wrappers = self._evaluator.execute_evaluated(decorator, old_func)
|
||||||
wrappers = self._evaluator.execute(decorator, (arg,))
|
|
||||||
if not len(wrappers):
|
if not len(wrappers):
|
||||||
debug.warning('no wrappers found %s', self.base_func)
|
debug.warning('no wrappers found %s', self.base_func)
|
||||||
return self
|
return self
|
||||||
|
|||||||
@@ -358,11 +358,13 @@ def nested_kw(**kwargs1):
|
|||||||
def nested_kw2(**kwargs2):
|
def nested_kw2(**kwargs2):
|
||||||
return nested_kw(**kwargs2)
|
return nested_kw(**kwargs2)
|
||||||
|
|
||||||
#? int()
|
# invalid command, doesn't need to return anything
|
||||||
|
#?
|
||||||
nested_kw(b=1, c=1.0, list)
|
nested_kw(b=1, c=1.0, list)
|
||||||
#? int()
|
#? int()
|
||||||
nested_kw(b=1)
|
nested_kw(b=1)
|
||||||
#? int()
|
# invalid command, doesn't need to return anything
|
||||||
|
#?
|
||||||
nested_kw(d=1.0, b=1, list)
|
nested_kw(d=1.0, b=1, list)
|
||||||
#? int()
|
#? int()
|
||||||
nested_kw(a=3.0, b=1)
|
nested_kw(a=3.0, b=1)
|
||||||
@@ -395,10 +397,12 @@ def nested_both(*args, **kwargs):
|
|||||||
def nested_both2(*args, **kwargs):
|
def nested_both2(*args, **kwargs):
|
||||||
return nested_both(*args, **kwargs)
|
return nested_both(*args, **kwargs)
|
||||||
|
|
||||||
#? int()
|
# invalid commands, may return whatever.
|
||||||
|
#? list
|
||||||
nested_both('', b=1, c=1.0, list)
|
nested_both('', b=1, c=1.0, list)
|
||||||
#? int()
|
#? list
|
||||||
nested_both('', c=1.0, b=1, list)
|
nested_both('', c=1.0, b=1, list)
|
||||||
|
|
||||||
#? []
|
#? []
|
||||||
nested_both('')
|
nested_both('')
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user