mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-09 23:34:45 +08:00
*args / **kwargs done - untested
This commit is contained in:
146
evaluate.py
146
evaluate.py
@@ -60,12 +60,24 @@ class Executable(object):
|
|||||||
""" An instance is also an executable - because __init__ is called """
|
""" An instance is also an executable - because __init__ is called """
|
||||||
def __init__(self, base, var_args=[]):
|
def __init__(self, base, var_args=[]):
|
||||||
self.base = base
|
self.base = base
|
||||||
|
# the param input array
|
||||||
self.var_args = var_args
|
self.var_args = var_args
|
||||||
self.func = None
|
self.func = None
|
||||||
|
|
||||||
def get_parent_until(self, *args):
|
def get_parent_until(self, *args):
|
||||||
return self.base.get_parent_until(*args)
|
return self.base.get_parent_until(*args)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def scope(self):
|
||||||
|
""" Just try through the whole param array to find the own scope """
|
||||||
|
for param in self.var_args:
|
||||||
|
for call in param:
|
||||||
|
try:
|
||||||
|
return call.parent_stmt.parent
|
||||||
|
except AttributeError: # if operators are there
|
||||||
|
pass
|
||||||
|
raise IndexError('No params available')
|
||||||
|
|
||||||
@memoize(default=[])
|
@memoize(default=[])
|
||||||
def get_params(self):
|
def get_params(self):
|
||||||
"""
|
"""
|
||||||
@@ -84,35 +96,55 @@ class Executable(object):
|
|||||||
self_name = copy.copy(self.func.params[0].get_name())
|
self_name = copy.copy(self.func.params[0].get_name())
|
||||||
self_name.parent = self.func.instance
|
self_name.parent = self.func.instance
|
||||||
result.append(self_name)
|
result.append(self_name)
|
||||||
|
|
||||||
|
param_dict = {}
|
||||||
|
for param in self.func.params:
|
||||||
|
# print 'para', param.get_name()
|
||||||
|
param_dict[str(param.get_name())] = param
|
||||||
# There may be calls, which don't fit all the params, this just ignores
|
# There may be calls, which don't fit all the params, this just ignores
|
||||||
# it.
|
# it.
|
||||||
param_iterator = iter(self.var_args)
|
var_arg_iterator = self.get_var_args_iterator()
|
||||||
for i, value in enumerate(param_iterator, start_offset):
|
for i, (key, value) in enumerate(var_arg_iterator, start_offset):
|
||||||
|
param = None
|
||||||
try:
|
try:
|
||||||
param = self.func.params[i]
|
param = param_dict[key]
|
||||||
except IndexError:
|
except:
|
||||||
debug.warning('Too many arguments given.', value)
|
try:
|
||||||
else:
|
param = self.func.params[i]
|
||||||
|
except IndexError:
|
||||||
|
debug.warning('Too many arguments given.', value)
|
||||||
|
|
||||||
|
if param:
|
||||||
calls = parsing.Array(parsing.Array.NOARRAY,
|
calls = parsing.Array(parsing.Array.NOARRAY,
|
||||||
self.var_args.parent_stmt)
|
self.var_args.parent_stmt)
|
||||||
|
|
||||||
assignment = param.get_assignment_calls().values[0]
|
assignment = param.get_assignment_calls().values[0]
|
||||||
calls.values = [value]
|
|
||||||
|
|
||||||
if assignment[0] == '*':
|
if assignment[0] == '*':
|
||||||
# it is a *args param
|
# *args param
|
||||||
print '\n\n*', assignment
|
print '\n\n3*', value, assignment
|
||||||
for value in param_iterator:
|
|
||||||
print value
|
|
||||||
calls.values.append(value)
|
|
||||||
calls.type = parsing.Array.TUPLE
|
calls.type = parsing.Array.TUPLE
|
||||||
|
if key:
|
||||||
|
var_arg_iterator.push_back(key, value)
|
||||||
|
else:
|
||||||
|
calls.values = [value]
|
||||||
|
for key, value in var_arg_iterator:
|
||||||
|
if key:
|
||||||
|
var_arg_iterator.push_back(key, value)
|
||||||
|
break
|
||||||
|
calls.values.append(value)
|
||||||
elif assignment[0] == '**':
|
elif assignment[0] == '**':
|
||||||
for value in param_iterator:
|
# **kwargs param
|
||||||
print value
|
|
||||||
calls.values.append(value)
|
|
||||||
calls.type = parsing.Array.DICT
|
calls.type = parsing.Array.DICT
|
||||||
|
calls.values = [value]
|
||||||
|
calls.keys = [key]
|
||||||
|
for value in var_arg_iterator:
|
||||||
|
calls.values.append(value)
|
||||||
|
calls.keys.append(key)
|
||||||
# it is a **args param
|
# it is a **args param
|
||||||
print '\n\n**', assignment
|
print '\n\n**', key, value, assignment
|
||||||
|
else:
|
||||||
|
# normal param
|
||||||
|
calls.values = [value]
|
||||||
|
|
||||||
new_param = copy.copy(param)
|
new_param = copy.copy(param)
|
||||||
new_param._assignment_calls = calls
|
new_param._assignment_calls = calls
|
||||||
@@ -122,8 +154,64 @@ class Executable(object):
|
|||||||
result.append(name)
|
result.append(name)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def var_args_iterator(self):
|
def get_var_args_iterator(self):
|
||||||
yield
|
"""
|
||||||
|
Yields a key/value pair, the key is None, if its not a named arg.
|
||||||
|
"""
|
||||||
|
def iterate():
|
||||||
|
# var_args is typically an Array, and not a list
|
||||||
|
for var_arg in self.var_args:
|
||||||
|
print '\nv', var_arg
|
||||||
|
# *args
|
||||||
|
if var_arg[0] == '*':
|
||||||
|
arrays = follow_call_list(self.scope, [var_arg[1:]])
|
||||||
|
for array in arrays:
|
||||||
|
for field in array.get_contents():
|
||||||
|
yield None, field
|
||||||
|
# **kwargs
|
||||||
|
elif var_arg[0] == '**':
|
||||||
|
arrays = follow_call_list(self.scope, [var_arg[1:]])
|
||||||
|
for array in arrays:
|
||||||
|
for key, field in array.get_contents():
|
||||||
|
yield key[0].name, field
|
||||||
|
print '**', var_arg
|
||||||
|
yield var_arg
|
||||||
|
# normal arguments (including key arguments)
|
||||||
|
else:
|
||||||
|
if len(var_arg) > 1 and var_arg[1] == '=':
|
||||||
|
# this is a named parameter
|
||||||
|
print '\nnix', var_arg[0].name, '\n'
|
||||||
|
yield var_arg[0].name, var_arg[2:]
|
||||||
|
else:
|
||||||
|
yield None, var_arg
|
||||||
|
|
||||||
|
class PushBackIterator(object):
|
||||||
|
def __init__(self, iterator):
|
||||||
|
self.pushes = []
|
||||||
|
self.iterator = iterator
|
||||||
|
|
||||||
|
def push_back(self, key, value):
|
||||||
|
self.pushes.append((key,value))
|
||||||
|
print 'pushed back', self.pushes
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def next(self):
|
||||||
|
""" Python 2 Compatibility """
|
||||||
|
return self.__next__()
|
||||||
|
|
||||||
|
def __next__(self):
|
||||||
|
try:
|
||||||
|
return self.pushes.pop()
|
||||||
|
except IndexError:
|
||||||
|
return next(self.iterator)
|
||||||
|
|
||||||
|
print 'va', self.var_args
|
||||||
|
#print 'va2', self.var_args[0]
|
||||||
|
|
||||||
|
return iter(PushBackIterator(iterate()))
|
||||||
|
|
||||||
|
|
||||||
def set_param_cb(self, func):
|
def set_param_cb(self, func):
|
||||||
self.func = func
|
self.func = func
|
||||||
@@ -149,7 +237,7 @@ class Instance(Executable):
|
|||||||
normally self
|
normally self
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return func.var_args[0].used_vars[0].names[0]
|
return func.params[0].used_vars[0].names[0]
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -280,7 +368,8 @@ class Execution(Executable):
|
|||||||
#s.parent = temp
|
#s.parent = temp
|
||||||
|
|
||||||
# reset the callback function on exit
|
# reset the callback function on exit
|
||||||
self.base.param_cb = None
|
# TODO how can we deactivate this again?
|
||||||
|
#self.base.param_cb = None
|
||||||
else:
|
else:
|
||||||
debug.warning("no execution possible", self.base)
|
debug.warning("no execution possible", self.base)
|
||||||
|
|
||||||
@@ -326,6 +415,9 @@ class Array(object):
|
|||||||
names = scope.get_defined_names()
|
names = scope.get_defined_names()
|
||||||
return [ArrayElement(n) for n in names]
|
return [ArrayElement(n) for n in names]
|
||||||
|
|
||||||
|
def get_contents(self):
|
||||||
|
return self._array
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<p%s of %s>" % (self.__class__.__name__, self._array)
|
return "<p%s of %s>" % (self.__class__.__name__, self._array)
|
||||||
|
|
||||||
@@ -560,11 +652,13 @@ def follow_statement(stmt, scope=None, seek_name=None):
|
|||||||
|
|
||||||
call_list = stmt.get_assignment_calls()
|
call_list = stmt.get_assignment_calls()
|
||||||
debug.dbg('calls', call_list, call_list.values)
|
debug.dbg('calls', call_list, call_list.values)
|
||||||
result = set(follow_call_list(scope, call_list))
|
result = follow_call_list(scope, call_list)
|
||||||
|
|
||||||
# assignment checking is only important if the statement defines multiple
|
# assignment checking is only important if the statement defines multiple
|
||||||
# variables
|
# variables
|
||||||
if len(stmt.get_set_vars()) > 1 and seek_name and stmt.assignment_details:
|
if len(stmt.get_set_vars()) > 1 and seek_name and stmt.assignment_details:
|
||||||
|
# TODO this should have its own call_list, because call_list can also
|
||||||
|
# return 3 results for 2 variables.
|
||||||
new_result = []
|
new_result = []
|
||||||
for op, set_vars in stmt.assignment_details:
|
for op, set_vars in stmt.assignment_details:
|
||||||
new_result += assign_tuples(set_vars, result, seek_name)
|
new_result += assign_tuples(set_vars, result, seek_name)
|
||||||
@@ -574,8 +668,10 @@ def follow_statement(stmt, scope=None, seek_name=None):
|
|||||||
|
|
||||||
def follow_call_list(scope, call_list):
|
def follow_call_list(scope, call_list):
|
||||||
"""
|
"""
|
||||||
The call list has a special structure.
|
The call_list has a special structure.
|
||||||
This can be either `parsing.Array` or `list`.
|
This can be either `parsing.Array` or `list of list`.
|
||||||
|
It is used to evaluate a two dimensional object, that has calls, arrays and
|
||||||
|
operators in it.
|
||||||
"""
|
"""
|
||||||
if parsing.Array.is_type(call_list, parsing.Array.TUPLE):
|
if parsing.Array.is_type(call_list, parsing.Array.TUPLE):
|
||||||
# Tuples can stand just alone without any braces. These would be
|
# Tuples can stand just alone without any braces. These would be
|
||||||
@@ -591,7 +687,7 @@ def follow_call_list(scope, call_list):
|
|||||||
if not isinstance(call, str):
|
if not isinstance(call, str):
|
||||||
# The string tokens are just operations (+, -, etc.)
|
# The string tokens are just operations (+, -, etc.)
|
||||||
result += follow_call(scope, call)
|
result += follow_call(scope, call)
|
||||||
return result
|
return set(result)
|
||||||
|
|
||||||
|
|
||||||
def follow_call(scope, call):
|
def follow_call(scope, call):
|
||||||
|
|||||||
@@ -845,7 +845,7 @@ class Array(Call):
|
|||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
if self.type == self.DICT:
|
if self.type == self.DICT:
|
||||||
return iter(self.values.items())
|
return iter(zip(self.keys, self.values))
|
||||||
else:
|
else:
|
||||||
return iter(self.values)
|
return iter(self.values)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user