comments revised.

This commit is contained in:
David Halter
2012-07-12 01:04:11 +02:00
parent 28f12865d2
commit 19c7f470ca
+72 -86
View File
@@ -114,10 +114,8 @@ class CachedMetaClass(type):
class Executable(object): 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=parsing.Array(None, None)): def __init__(self, base, var_args=parsing.Array(None, None)):
#if var_args == []:
# raise NotImplementedError()
self.base = base self.base = base
# the param input array # The param input array.
self.var_args = var_args self.var_args = var_args
def get_parent_until(self, *args): def get_parent_until(self, *args):
@@ -134,7 +132,6 @@ class Instance(Executable):
@memoize_default() @memoize_default()
def get_init_execution(self, func): def get_init_execution(self, func):
if isinstance(func, parsing.Function): if isinstance(func, parsing.Function):
#self.set_param_cb(InstanceElement(self, Function(sub)))
instance_el = InstanceElement(self, Function(func)) instance_el = InstanceElement(self, Function(func))
return Execution(instance_el, self.var_args) return Execution(instance_el, self.var_args)
else: else:
@@ -163,13 +160,13 @@ class Instance(Executable):
names.append(InstanceElement(self, n)) names.append(InstanceElement(self, n))
names = [] names = []
# this loop adds the names of the self object, copies them and removes # This loop adds the names of the self object, copies them and removes
# the self. # the self.
for sub in self.base.subscopes: for sub in self.base.subscopes:
# get the self name, if there's one # Get the self name, if there's one.
self_name = self.get_func_self_name(sub) self_name = self.get_func_self_name(sub)
if self_name: if self_name:
# check the __init__ function # Check the __init__ function.
if self.var_args and sub.name.get_code() == '__init__': if self.var_args and sub.name.get_code() == '__init__':
sub = self.get_init_execution(sub) sub = self.get_init_execution(sub)
for n in sub.get_set_vars(): for n in sub.get_set_vars():
@@ -193,7 +190,7 @@ class Instance(Executable):
class_names = self.base.get_defined_names() class_names = self.base.get_defined_names()
for var in class_names: for var in class_names:
# functions are also instance elements # Functions are also instance elements.
if isinstance(var.parent, (Function, parsing.Function)): if isinstance(var.parent, (Function, parsing.Function)):
var = InstanceElement(self, var) var = InstanceElement(self, var)
names.append(var) names.append(var)
@@ -202,7 +199,7 @@ class Instance(Executable):
def get_descriptor_return(self, obj): def get_descriptor_return(self, obj):
""" Throws an error if there's no method. """ """ Throws an error if there's no method. """
method = self.get_subscope_by_name('__get__') method = self.get_subscope_by_name('__get__')
# arguments in __set__ descriptors are obj, class. # Arguments in __set__ 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 = parsing.Array('tuple', method, values=[[obj], [obj.base]]) args = parsing.Array('tuple', method, values=[[obj], [obj.base]])
method = InstanceElement(self, method) method = InstanceElement(self, method)
@@ -212,7 +209,7 @@ class Instance(Executable):
def __getattr__(self, name): def __getattr__(self, name):
if name == 'get_index_types': if name == 'get_index_types':
# todo call __getitem__ in such cases? # TODO Call __getitem__ in such cases?
return lambda: [] return lambda: []
if name not in ['line_nr', 'indent', 'name', 'get_imports']: if name not in ['line_nr', 'indent', 'name', 'get_imports']:
raise AttributeError("Instance %s: Don't touch this (%s)!" raise AttributeError("Instance %s: Don't touch this (%s)!"
@@ -245,13 +242,12 @@ class InstanceElement(object):
return InstanceElement(self.instance, scope) return InstanceElement(self.instance, scope)
def get_assignment_calls(self): def get_assignment_calls(self):
# copy and modify the array # Copy and modify the array.
origin = self.var.get_assignment_calls() origin = self.var.get_assignment_calls()
origin.parent_stmt, temp = None, origin.parent_stmt origin.parent_stmt, temp = None, origin.parent_stmt
new = copy.deepcopy(origin) new = copy.deepcopy(origin)
origin.parent_stmt = temp origin.parent_stmt = temp
new.parent_stmt = InstanceElement(self.instance, temp) new.parent_stmt = InstanceElement(self.instance, temp)
#print 'gac', new, new.parent_stmt, new.parent_stmt.instance
return new return new
def __getattr__(self, name): def __getattr__(self, name):
@@ -270,13 +266,13 @@ class Class(object):
@memoize_default(default=[]) @memoize_default(default=[])
def get_super_classes(self): def get_super_classes(self):
supers = [] supers = []
# TODO care for mro stuff (multiple super classes) # TODO care for mro stuff (multiple super classes).
for s in self.base.supers: for s in self.base.supers:
# super classes are statements # Super classes are statements.
for cls in follow_statement(s): for cls in follow_statement(s):
if not isinstance(cls, Class): if not isinstance(cls, Class):
debug.warning('Received non class, as a super class') debug.warning('Received non class, as a super class')
continue # just ignore other stuff (user input error) continue # Just ignore other stuff (user input error).
supers.append(cls) supers.append(cls)
return supers return supers
@@ -285,7 +281,7 @@ class Class(object):
def in_iterable(name, iterable): def in_iterable(name, iterable):
""" checks if the name is in the variable 'iterable'. """ """ checks if the name is in the variable 'iterable'. """
for i in iterable: for i in iterable:
# only the last name is important, because these names have a # Only the last name is important, because these names have a
# maximal length of 2, with the first one being `self`. # maximal length of 2, with the first one being `self`.
if i.names[-1] == name.names[-1]: if i.names[-1] == name.names[-1]:
return True return True
@@ -294,7 +290,7 @@ class Class(object):
result = self.base.get_defined_names() result = self.base.get_defined_names()
super_result = [] super_result = []
for cls in self.get_super_classes(): for cls in self.get_super_classes():
# get the inherited names # Get the inherited names.
for i in cls.get_defined_names(): for i in cls.get_defined_names():
if not in_iterable(i, result): if not in_iterable(i, result):
super_result.append(i) super_result.append(i)
@@ -334,7 +330,7 @@ class Function(object):
""" """
f = self.base_func f = self.base_func
# only enter it, if has not already been processed # Only enter it, if has not already been processed.
if not self.is_decorated: if not self.is_decorated:
for dec in reversed(self.base_func.decorators): for dec in reversed(self.base_func.decorators):
debug.dbg('decorator:', dec, f) debug.dbg('decorator:', dec, f)
@@ -347,7 +343,7 @@ class Function(object):
debug.warning('multiple decorators found', self.base_func, debug.warning('multiple decorators found', self.base_func,
dec_results) dec_results)
decorator = dec_results.pop() decorator = dec_results.pop()
# create param array # Create param array.
old_func = Function(f, is_decorated=True) old_func = Function(f, is_decorated=True)
params = parsing.Array(parsing.Array.NOARRAY, old_func) params = parsing.Array(parsing.Array.NOARRAY, old_func)
params.values = [[old_func]] params.values = [[old_func]]
@@ -359,7 +355,7 @@ class Function(object):
if len(wrappers) > 1: if len(wrappers) > 1:
debug.warning('multiple wrappers found', self.base_func, debug.warning('multiple wrappers found', self.base_func,
wrappers) wrappers)
# this is here, that the wrapper gets executed # This is here, that the wrapper gets executed.
f = wrappers[0] f = wrappers[0]
debug.dbg('decorator end', f) debug.dbg('decorator end', f)
@@ -394,21 +390,20 @@ class Execution(Executable):
""" """
Get the return vars of a function. Get the return vars of a function.
""" """
#a = self.var_args; print '\n\n', a, a.values, a.parent_stmt
stmts = [] stmts = []
if isinstance(self.base, Class): if isinstance(self.base, Class):
# there maybe executions of executions # There maybe executions of executions.
stmts = [Instance(self.base, self.var_args)] stmts = [Instance(self.base, self.var_args)]
elif isinstance(self.base, Generator): elif isinstance(self.base, Generator):
return self.base.execute() return self.base.execute()
else: else:
# don't do this with exceptions, as usual, because some deeper # Don't do this with exceptions, as usual, because some deeper
# exceptions could be catched - and I wouldn't know what happened. # exceptions could be catched - and I wouldn't know what happened.
if hasattr(self.base, 'returns'): if hasattr(self.base, 'returns'):
stmts = self._get_function_returns(evaluate_generator) stmts = self._get_function_returns(evaluate_generator)
else: else:
try: try:
# if it is an instance, we try to execute the __call__(). # If it is an instance, we try to execute the __call__().
call_method = self.base.get_subscope_by_name('__call__') call_method = self.base.get_subscope_by_name('__call__')
except (AttributeError, KeyError, DecoratorNotFound): except (AttributeError, KeyError, DecoratorNotFound):
debug.warning("no execution possible", self.base) debug.warning("no execution possible", self.base)
@@ -458,14 +453,12 @@ class Execution(Executable):
new_param._assignment_calls = calls new_param._assignment_calls = calls
name = copy.copy(param.get_name()) name = copy.copy(param.get_name())
name.parent = new_param name.parent = new_param
#print 'insert', i, name, calls.values, value, self.base.params
return name return name
result = [] result = []
start_offset = 0 start_offset = 0
#print '\n\nfunc_params', self.base, self.base.parent, self.base
if isinstance(self.base, InstanceElement): if isinstance(self.base, InstanceElement):
# care for self -> just exclude it and add the instance # Care for self -> just exclude it and add the instance
start_offset = 1 start_offset = 1
self_name = copy.copy(self.base.params[0].get_name()) self_name = copy.copy(self.base.params[0].get_name())
self_name.parent = self.base.instance self_name.parent = self.base.instance
@@ -483,6 +476,9 @@ class Execution(Executable):
for param in self.base.params[start_offset:]: for param in self.base.params[start_offset:]:
# The value and key can both be null. There, the defaults apply. # The value and key can both be null. There, the defaults apply.
# args / kwargs will just be empty arrays / dicts, respectively. # args / kwargs will just be empty arrays / dicts, respectively.
# Wrong value count is just ignored. If you try to test cases which
# are not allowed in Python, Jedi will maybe not show any
# completions.
key, value = next(var_arg_iterator, (None, None)) key, value = next(var_arg_iterator, (None, None))
while key: while key:
try: try:
@@ -495,8 +491,6 @@ class Execution(Executable):
key, value = next(var_arg_iterator, (None, None)) key, value = next(var_arg_iterator, (None, None))
keys_only = True keys_only = True
#debug.warning('Too many arguments given.', value)
assignments = param.get_assignment_calls().values assignments = param.get_assignment_calls().values
assignment = assignments[0] assignment = assignments[0]
keys = [] keys = []
@@ -508,7 +502,7 @@ class Execution(Executable):
if value: if value:
values.append(value) values.append(value)
for key, value in var_arg_iterator: for key, value in var_arg_iterator:
# iterate until a key argument is found # Iterate until a key argument is found.
if key: if key:
var_arg_iterator.push_back(key, value) var_arg_iterator.push_back(key, value)
break break
@@ -523,11 +517,10 @@ class Execution(Executable):
if value: if value:
values = [value] values = [value]
else: else:
# just give it the default values (if there's something # No value: return the default values.
# there)
values = assignments values = assignments
# just ignore all the params that are without a key, after one # Just ignore all the params that are without a key, after one
# keyword argument was set. # keyword argument was set.
if not keys_only or assignment[0] == '**': if not keys_only or assignment[0] == '**':
result.append(gen_param_name_copy(param, keys=keys, result.append(gen_param_name_copy(param, keys=keys,
@@ -539,7 +532,7 @@ class Execution(Executable):
Yields a key/value pair, the key is None, if its not a named arg. Yields a key/value pair, the key is None, if its not a named arg.
""" """
def iterate(): def iterate():
# var_args is typically an Array, and not a list # `var_args` is typically an Array, and not a list.
for var_arg in self.var_args: for var_arg in self.var_args:
# *args # *args
if var_arg[0] == '*': if var_arg[0] == '*':
@@ -552,17 +545,17 @@ class Execution(Executable):
arrays = follow_call_list([var_arg[1:]]) arrays = follow_call_list([var_arg[1:]])
for array in arrays: for array in arrays:
for key, field in array.get_contents(): for key, field in array.get_contents():
# take the first index # Take the first index.
if isinstance(key, parsing.Name): if isinstance(key, parsing.Name):
name = key name = key
else: else:
# parsing.[Call|Function|Class] lookup # `parsing`.[Call|Function|Class] lookup.
name = key[0].name name = key[0].name
yield name, field yield name, field
# normal arguments (including key arguments) # Normal arguments (including key arguments).
else: else:
if len(var_arg) > 1 and var_arg[1] == '=': if len(var_arg) > 1 and var_arg[1] == '=':
# this is a named parameter (var_arg[0] is a Call) # This is a named parameter (var_arg[0] is a Call).
yield var_arg[0].name, var_arg[2:] yield var_arg[0].name, var_arg[2:]
else: else:
yield None, var_arg yield None, var_arg
@@ -601,7 +594,7 @@ class Execution(Executable):
return self.get_params() + parsing.Scope._get_set_vars(self) return self.get_params() + parsing.Scope._get_set_vars(self)
def copy_properties(self, prop): def copy_properties(self, prop):
# copy all these lists into this local function. # Copy all these lists into this local function.
attr = getattr(self.base, prop) attr = getattr(self.base, prop)
objects = [] objects = []
for element in attr: for element in attr:
@@ -652,12 +645,11 @@ class Generator(object):
""" """
names = [] names = []
for n in ['__next__', 'send']: for n in ['__next__', 'send']:
# the name for the `next` function # The name for the `next` function.
name = parsing.Name([n], 0, 0, 0) name = parsing.Name([n], 0, 0, 0)
name.parent = self name.parent = self
names.append(name) names.append(name)
for n in ['close', 'throw']: for n in ['close', 'throw']:
# the name for the `next` function
name = parsing.Name([n], 0, 0, 0) name = parsing.Name([n], 0, 0, 0)
name.parent = None name.parent = None
names.append(name) names.append(name)
@@ -695,9 +687,9 @@ class Array(object):
return [self] return [self]
else: else:
# This is indexing only one element, with a fixed index number, # This is indexing only one element, with a fixed index number,
# otherwise it just ignores the index (e.g. [1+1]) # otherwise it just ignores the index (e.g. [1+1]).
try: try:
# multiple elements in the array # Multiple elements in the array.
i = index.get_only_subelement().name i = index.get_only_subelement().name
except AttributeError: except AttributeError:
pass pass
@@ -713,7 +705,7 @@ class Array(object):
old_index = index old_index = index
index = None index = None
for i, key_elements in enumerate(self._array.keys): for i, key_elements in enumerate(self._array.keys):
# because we only want the key to be a string # Because we only want the key to be a string.
if len(key_elements) == 1: if len(key_elements) == 1:
try: try:
str_key = key_elements.get_code() str_key = key_elements.get_code()
@@ -739,7 +731,7 @@ class Array(object):
This method generates all ArrayElements for one parsing.Array. This method generates all ArrayElements for one parsing.Array.
It returns e.g. for a list: append, pop, ... It returns e.g. for a list: append, pop, ...
""" """
# array.type is a string with the type, e.g. 'list' # `array.type` is a string with the type, e.g. 'list'.
scope = get_scopes_for_name(builtin.Builtin.scope, self._array.type)[0] scope = get_scopes_for_name(builtin.Builtin.scope, self._array.type)[0]
names = scope.get_defined_names() names = scope.get_defined_names()
return [ArrayElement(n) for n in names] return [ArrayElement(n) for n in names]
@@ -769,7 +761,7 @@ class ArrayElement(object):
self.name = name self.name = name
def __getattr__(self, name): def __getattr__(self, name):
# set access rights: # Set access privileges:
if name not in ['parent', 'names', 'line_nr', 'indent']: if name not in ['parent', 'names', 'line_nr', 'indent']:
raise AttributeError('Strange access: %s.' % name) raise AttributeError('Strange access: %s.' % name)
return getattr(self.name, name) return getattr(self.name, name)
@@ -783,7 +775,7 @@ def get_defined_names_for_position(obj, position=None, start_scope=None):
:param position: the position as a row/column tuple, default is infinity. :param position: the position as a row/column tuple, default is infinity.
""" """
names = obj.get_defined_names() names = obj.get_defined_names()
# instances have special rules, always return all the possible completions, # Instances have special rules, always return all the possible completions,
# because class variables are always valid and the `self.` variables, too. # because class variables are always valid and the `self.` variables, too.
if not position or isinstance(obj, Instance) or isinstance(obj, Function) \ if not position or isinstance(obj, Instance) or isinstance(obj, Function) \
and isinstance(obj.decorated_func, Instance) \ and isinstance(obj.decorated_func, Instance) \
@@ -806,7 +798,7 @@ def get_names_for_scope(scope, position=None, star_search=True):
start_scope = scope start_scope = scope
while scope: while scope:
# `parsing.Class` is used, because the parent is never `Class`. # `parsing.Class` is used, because the parent is never `Class`.
# ignore the Flows, because the classes and functions care for that. # Ignore the Flows, because the classes and functions care for that.
if not (scope != start_scope and isinstance(scope, parsing.Class) if not (scope != start_scope and isinstance(scope, parsing.Class)
or isinstance(scope, parsing.Flow) or isinstance(scope, parsing.Flow)
or isinstance(scope, InstanceElement) or isinstance(scope, InstanceElement)
@@ -818,13 +810,13 @@ def get_names_for_scope(scope, position=None, star_search=True):
raise MultiLevelStopIteration('StopIteration raised somewhere') raise MultiLevelStopIteration('StopIteration raised somewhere')
scope = scope.parent scope = scope.parent
# add star imports # Add star imports.
if star_search: if star_search:
for s in remove_star_imports(start_scope.get_parent_until()): for s in remove_star_imports(start_scope.get_parent_until()):
for g in get_names_for_scope(s, star_search=False): for g in get_names_for_scope(s, star_search=False):
yield g yield g
# add builtins to the global scope # Add builtins to the global scope.
builtin_scope = builtin.Builtin.scope builtin_scope = builtin.Builtin.scope
yield builtin_scope, builtin_scope.get_defined_names() yield builtin_scope, builtin_scope.get_defined_names()
@@ -847,7 +839,7 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False):
if isinstance(r, parsing.Statement) \ if isinstance(r, parsing.Statement) \
or isinstance(r, InstanceElement) \ or isinstance(r, InstanceElement) \
and isinstance(r.var, parsing.Statement): and isinstance(r.var, parsing.Statement):
# global variables handling # Global variables handling.
if r.is_global(): if r.is_global():
for token_name in r.token_list[1:]: for token_name in r.token_list[1:]:
if isinstance(token_name, parsing.Name): if isinstance(token_name, parsing.Name):
@@ -871,9 +863,9 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False):
par = name.parent par = name.parent
if isinstance(par, parsing.Flow): if isinstance(par, parsing.Flow):
if par.command == 'for': if par.command == 'for':
# take the first statement (for has always only # Take the first statement (for has always only
# one, remember `in`). And follow it. After that, # one, remember `in`). And follow it. After that,
# get the types which are in the array # get the types which are in the array.
arrays = follow_statement(par.inits[0]) arrays = follow_statement(par.inits[0])
for array in arrays: for array in arrays:
in_vars = array.get_index_types() in_vars = array.get_index_types()
@@ -887,8 +879,8 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False):
elif isinstance(par, parsing.Param) \ elif isinstance(par, parsing.Param) \
and isinstance(par.parent.parent, parsing.Class) \ and isinstance(par.parent.parent, parsing.Class) \
and par.position == 0: and par.position == 0:
# this is where self gets added - this happens at another # This is where self gets added - this happens at another
# place, if the var_args are clear. But some times the class is # place, if the var_args are clear. But sometimes the class is
# not known. Therefore add a new instance for self. Otherwise # not known. Therefore add a new instance for self. Otherwise
# take the existing. # take the existing.
if isinstance(scope, InstanceElement): if isinstance(scope, InstanceElement):
@@ -899,10 +891,6 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False):
elif isinstance(par, (InstanceElement)) \ elif isinstance(par, (InstanceElement)) \
and hasattr(par, 'get_descriptor_return'): and hasattr(par, 'get_descriptor_return'):
try: try:
#print '\n\n'
#print name, par
#print par.get_descriptor_return(scope)
#raise KeyError()
result += par.get_descriptor_return(scope) result += par.get_descriptor_return(scope)
except KeyError: except KeyError:
result.append(par) result.append(par)
@@ -914,7 +902,6 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False):
# compare func uses the tuple of line/indent = row/column # compare func uses the tuple of line/indent = row/column
comparison_func = lambda name: (name.line_nr, name.indent) comparison_func = lambda name: (name.line_nr, name.indent)
for scope, name_list in scope_generator: for scope, name_list in scope_generator:
#print scope, name_list[:9]
break_scopes = [] break_scopes = []
# here is the position stuff happening (sorting of variables) # here is the position stuff happening (sorting of variables)
for name in sorted(name_list, key=comparison_func, reverse=True): for name in sorted(name_list, key=comparison_func, reverse=True):
@@ -956,7 +943,6 @@ def strip_imports(scopes):
result = [] result = []
for s in scopes: for s in scopes:
if isinstance(s, parsing.Import): if isinstance(s, parsing.Import):
#print 'dini mueter, steile griech!'
try: try:
result += follow_import(s) result += follow_import(s)
except modules.ModuleNotFound: except modules.ModuleNotFound:
@@ -991,20 +977,20 @@ def assign_tuples(tup, results, seek_name):
result = [] result = []
if tup.type == parsing.Array.NOARRAY: if tup.type == parsing.Array.NOARRAY:
# here we have unnessecary braces, which we just remove # Here we have unnessecary braces, which we just remove.
arr = tup.get_only_subelement() arr = tup.get_only_subelement()
result = assign_tuples(arr, results, seek_name) result = assign_tuples(arr, results, seek_name)
else: else:
for i, t in enumerate(tup): for i, t in enumerate(tup):
# used in assignments. there is just one call and no other things, # Used in assignments. There is just one call and no other things,
# therefor we can just assume, that the first part is important. # therefore we can just assume, that the first part is important.
if len(t) != 1: if len(t) != 1:
raise AttributeError('Array length should be 1') raise AttributeError('Array length should be 1')
t = t[0] t = t[0]
# check the left part, if it's still tuples in it or a Call # Check the left part, if there are still tuples in it or a Call.
if isinstance(t, parsing.Array): if isinstance(t, parsing.Array):
# these are "sub" tuples # These are "sub"-tuples.
result += assign_tuples(t, eval_results(i), seek_name) result += assign_tuples(t, eval_results(i), seek_name)
else: else:
if t.name.names[-1] == seek_name: if t.name.names[-1] == seek_name:
@@ -1030,10 +1016,10 @@ def follow_statement(stmt, seek_name=None):
# errors here must not be catched, because they shouldn't exist. # errors here must not be catched, because they shouldn't exist.
raise MultiLevelAttributeError(sys.exc_info()) raise MultiLevelAttributeError(sys.exc_info())
# 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 # TODO This should have its own call_list, because call_list can also
# return 3 results for 2 variables. # 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:
@@ -1062,13 +1048,13 @@ def follow_call_list(call_list):
if parsing.Array.is_type(call, parsing.Array.NOARRAY): if parsing.Array.is_type(call, parsing.Array.NOARRAY):
result += follow_call_list(call) result += follow_call_list(call)
else: else:
# with things like params, these can also be functions, etc # With things like params, these can also be functions...
if isinstance(call, (Function, parsing.Class, Instance)): if isinstance(call, (Function, parsing.Class, Instance)):
result.append(call) result.append(call)
# The string tokens are just operations (+, -, etc.) # The string tokens are just operations (+, -, etc.)
elif not isinstance(call, str): elif not isinstance(call, str):
# ternary operators # Ternary operators.
#if str(call.name) == 'for': #if str(call.name) == 'for': <--- list comprehensions
# print '\n\ndini mueter' # print '\n\ndini mueter'
if str(call.name) == 'if': if str(call.name) == 'if':
while True: while True:
@@ -1101,16 +1087,16 @@ def follow_call(call):
else: else:
debug.warning('unknown type:', current.type, current) debug.warning('unknown type:', current.type, current)
scopes = [] scopes = []
# make instances of those number/string objects # Make instances of those number/string objects.
scopes = [Instance(s) for s in scopes] scopes = [Instance(s) for s in scopes]
else: else:
# this is the first global lookup # This is the first global lookup.
scopes = get_scopes_for_name(scope, current, position=position, scopes = get_scopes_for_name(scope, current, position=position,
search_global=True) search_global=True)
result = strip_imports(scopes) result = strip_imports(scopes)
if result != scopes: if result != scopes:
# reset the position, when imports where stripped # Reset the position, when imports where stripped.
position = None position = None
debug.dbg('before next follow %s, current "%s", scope %s' debug.dbg('before next follow %s, current "%s", scope %s'
@@ -1133,7 +1119,7 @@ def follow_paths(path, results, position=None):
if fp is not None: if fp is not None:
results_new += fp results_new += fp
else: else:
# this means stop iteration # This means stop iteration.
return results return results
return results_new return results_new
@@ -1142,7 +1128,7 @@ def follow_path(path, scope, position=None):
""" """
Takes a generator and tries to complete the path. Takes a generator and tries to complete the path.
""" """
# current is either an Array or a Scope # Current is either an Array or a Scope.
try: try:
current = next(path) current = next(path)
except StopIteration: except StopIteration:
@@ -1151,25 +1137,25 @@ def follow_path(path, scope, position=None):
result = [] result = []
if isinstance(current, parsing.Array): if isinstance(current, parsing.Array):
# this must be an execution, either () or [] # This must be an execution, either () or [].
if current.type == parsing.Array.LIST: if current.type == parsing.Array.LIST:
result = scope.get_index_types(current) result = scope.get_index_types(current)
elif current.type not in [parsing.Array.DICT]: elif current.type not in [parsing.Array.DICT]:
# scope must be a class or func - make an instance or execution # Scope must be a class or func - make an instance or execution.
debug.dbg('exe', scope) debug.dbg('exe', scope)
result = Execution(scope, current).get_return_types() result = Execution(scope, current).get_return_types()
else: else:
# curly braces are not allowed, because they make no sense # Curly braces are not allowed, because they make no sense.
debug.warning('strange function call with {}', current, scope) debug.warning('strange function call with {}', current, scope)
else: else:
# the function must not be decorated with something else # The function must not be decorated with something else.
if isinstance(scope, Function) and \ if isinstance(scope, Function) and \
isinstance(scope.decorated_func, Function): isinstance(scope.decorated_func, Function):
# TODO check default function methods and return them # TODO Check default function methods and return them.
result = [] result = []
else: else:
# TODO check magic class methods and return them also # TODO Check magic class methods and return them also.
# this is the typical lookup while chaining things # This is the typical lookup while chaining things.
result = strip_imports(get_scopes_for_name(scope, current, result = strip_imports(get_scopes_for_name(scope, current,
position=position)) position=position))
return follow_paths(path, result, position=position) return follow_paths(path, result, position=position)
@@ -1181,7 +1167,7 @@ def follow_import(_import):
:param _import: The import statement. :param _import: The import statement.
:type _import: parsing.Import :type _import: parsing.Import
""" """
# set path together # Set path together.
ns_list = [] ns_list = []
if _import.from_ns: if _import.from_ns:
ns_list += _import.from_ns.names ns_list += _import.from_ns.names
@@ -1214,5 +1200,5 @@ def remove_star_imports(scope):
new += remove_star_imports(m) new += remove_star_imports(m)
modules += new modules += new
# filter duplicate modules # Filter duplicate modules.
return set(modules) return set(modules)