forked from VimPlug/jedi
comments revised.
This commit is contained in:
158
evaluate.py
158
evaluate.py
@@ -114,10 +114,8 @@ class CachedMetaClass(type):
|
||||
class Executable(object):
|
||||
""" An instance is also an executable - because __init__ is called """
|
||||
def __init__(self, base, var_args=parsing.Array(None, None)):
|
||||
#if var_args == []:
|
||||
# raise NotImplementedError()
|
||||
self.base = base
|
||||
# the param input array
|
||||
# The param input array.
|
||||
self.var_args = var_args
|
||||
|
||||
def get_parent_until(self, *args):
|
||||
@@ -134,7 +132,6 @@ class Instance(Executable):
|
||||
@memoize_default()
|
||||
def get_init_execution(self, func):
|
||||
if isinstance(func, parsing.Function):
|
||||
#self.set_param_cb(InstanceElement(self, Function(sub)))
|
||||
instance_el = InstanceElement(self, Function(func))
|
||||
return Execution(instance_el, self.var_args)
|
||||
else:
|
||||
@@ -163,13 +160,13 @@ class Instance(Executable):
|
||||
names.append(InstanceElement(self, n))
|
||||
|
||||
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.
|
||||
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)
|
||||
if self_name:
|
||||
# check the __init__ function
|
||||
# Check the __init__ function.
|
||||
if self.var_args and sub.name.get_code() == '__init__':
|
||||
sub = self.get_init_execution(sub)
|
||||
for n in sub.get_set_vars():
|
||||
@@ -193,7 +190,7 @@ class Instance(Executable):
|
||||
|
||||
class_names = self.base.get_defined_names()
|
||||
for var in class_names:
|
||||
# functions are also instance elements
|
||||
# Functions are also instance elements.
|
||||
if isinstance(var.parent, (Function, parsing.Function)):
|
||||
var = InstanceElement(self, var)
|
||||
names.append(var)
|
||||
@@ -202,7 +199,7 @@ class Instance(Executable):
|
||||
def get_descriptor_return(self, obj):
|
||||
""" Throws an error if there's no method. """
|
||||
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.
|
||||
args = parsing.Array('tuple', method, values=[[obj], [obj.base]])
|
||||
method = InstanceElement(self, method)
|
||||
@@ -212,7 +209,7 @@ class Instance(Executable):
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name == 'get_index_types':
|
||||
# todo call __getitem__ in such cases?
|
||||
# TODO Call __getitem__ in such cases?
|
||||
return lambda: []
|
||||
if name not in ['line_nr', 'indent', 'name', 'get_imports']:
|
||||
raise AttributeError("Instance %s: Don't touch this (%s)!"
|
||||
@@ -245,13 +242,12 @@ class InstanceElement(object):
|
||||
return InstanceElement(self.instance, scope)
|
||||
|
||||
def get_assignment_calls(self):
|
||||
# copy and modify the array
|
||||
# Copy and modify the array.
|
||||
origin = self.var.get_assignment_calls()
|
||||
origin.parent_stmt, temp = None, origin.parent_stmt
|
||||
new = copy.deepcopy(origin)
|
||||
origin.parent_stmt = temp
|
||||
new.parent_stmt = InstanceElement(self.instance, temp)
|
||||
#print 'gac', new, new.parent_stmt, new.parent_stmt.instance
|
||||
return new
|
||||
|
||||
def __getattr__(self, name):
|
||||
@@ -270,13 +266,13 @@ class Class(object):
|
||||
@memoize_default(default=[])
|
||||
def get_super_classes(self):
|
||||
supers = []
|
||||
# TODO care for mro stuff (multiple super classes)
|
||||
# TODO care for mro stuff (multiple super classes).
|
||||
for s in self.base.supers:
|
||||
# super classes are statements
|
||||
# Super classes are statements.
|
||||
for cls in follow_statement(s):
|
||||
if not isinstance(cls, 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)
|
||||
return supers
|
||||
|
||||
@@ -285,7 +281,7 @@ class Class(object):
|
||||
def in_iterable(name, iterable):
|
||||
""" checks if the name is in the variable '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`.
|
||||
if i.names[-1] == name.names[-1]:
|
||||
return True
|
||||
@@ -294,7 +290,7 @@ class Class(object):
|
||||
result = self.base.get_defined_names()
|
||||
super_result = []
|
||||
for cls in self.get_super_classes():
|
||||
# get the inherited names
|
||||
# Get the inherited names.
|
||||
for i in cls.get_defined_names():
|
||||
if not in_iterable(i, result):
|
||||
super_result.append(i)
|
||||
@@ -334,7 +330,7 @@ class Function(object):
|
||||
"""
|
||||
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:
|
||||
for dec in reversed(self.base_func.decorators):
|
||||
debug.dbg('decorator:', dec, f)
|
||||
@@ -347,7 +343,7 @@ class Function(object):
|
||||
debug.warning('multiple decorators found', self.base_func,
|
||||
dec_results)
|
||||
decorator = dec_results.pop()
|
||||
# create param array
|
||||
# Create param array.
|
||||
old_func = Function(f, is_decorated=True)
|
||||
params = parsing.Array(parsing.Array.NOARRAY, old_func)
|
||||
params.values = [[old_func]]
|
||||
@@ -359,7 +355,7 @@ class Function(object):
|
||||
if len(wrappers) > 1:
|
||||
debug.warning('multiple wrappers found', self.base_func,
|
||||
wrappers)
|
||||
# this is here, that the wrapper gets executed
|
||||
# This is here, that the wrapper gets executed.
|
||||
f = wrappers[0]
|
||||
|
||||
debug.dbg('decorator end', f)
|
||||
@@ -394,21 +390,20 @@ class Execution(Executable):
|
||||
"""
|
||||
Get the return vars of a function.
|
||||
"""
|
||||
#a = self.var_args; print '\n\n', a, a.values, a.parent_stmt
|
||||
stmts = []
|
||||
if isinstance(self.base, Class):
|
||||
# there maybe executions of executions
|
||||
# There maybe executions of executions.
|
||||
stmts = [Instance(self.base, self.var_args)]
|
||||
elif isinstance(self.base, Generator):
|
||||
return self.base.execute()
|
||||
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.
|
||||
if hasattr(self.base, 'returns'):
|
||||
stmts = self._get_function_returns(evaluate_generator)
|
||||
else:
|
||||
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__')
|
||||
except (AttributeError, KeyError, DecoratorNotFound):
|
||||
debug.warning("no execution possible", self.base)
|
||||
@@ -458,14 +453,12 @@ class Execution(Executable):
|
||||
new_param._assignment_calls = calls
|
||||
name = copy.copy(param.get_name())
|
||||
name.parent = new_param
|
||||
#print 'insert', i, name, calls.values, value, self.base.params
|
||||
return name
|
||||
|
||||
result = []
|
||||
start_offset = 0
|
||||
#print '\n\nfunc_params', self.base, self.base.parent, self.base
|
||||
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
|
||||
self_name = copy.copy(self.base.params[0].get_name())
|
||||
self_name.parent = self.base.instance
|
||||
@@ -483,6 +476,9 @@ class Execution(Executable):
|
||||
for param in self.base.params[start_offset:]:
|
||||
# The value and key can both be null. There, the defaults apply.
|
||||
# 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))
|
||||
while key:
|
||||
try:
|
||||
@@ -495,8 +491,6 @@ class Execution(Executable):
|
||||
key, value = next(var_arg_iterator, (None, None))
|
||||
keys_only = True
|
||||
|
||||
#debug.warning('Too many arguments given.', value)
|
||||
|
||||
assignments = param.get_assignment_calls().values
|
||||
assignment = assignments[0]
|
||||
keys = []
|
||||
@@ -508,7 +502,7 @@ class Execution(Executable):
|
||||
if value:
|
||||
values.append(value)
|
||||
for key, value in var_arg_iterator:
|
||||
# iterate until a key argument is found
|
||||
# Iterate until a key argument is found.
|
||||
if key:
|
||||
var_arg_iterator.push_back(key, value)
|
||||
break
|
||||
@@ -523,11 +517,10 @@ class Execution(Executable):
|
||||
if value:
|
||||
values = [value]
|
||||
else:
|
||||
# just give it the default values (if there's something
|
||||
# there)
|
||||
# No value: return the default values.
|
||||
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.
|
||||
if not keys_only or assignment[0] == '**':
|
||||
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.
|
||||
"""
|
||||
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:
|
||||
# *args
|
||||
if var_arg[0] == '*':
|
||||
@@ -552,17 +545,17 @@ class Execution(Executable):
|
||||
arrays = follow_call_list([var_arg[1:]])
|
||||
for array in arrays:
|
||||
for key, field in array.get_contents():
|
||||
# take the first index
|
||||
# Take the first index.
|
||||
if isinstance(key, parsing.Name):
|
||||
name = key
|
||||
else:
|
||||
# parsing.[Call|Function|Class] lookup
|
||||
# `parsing`.[Call|Function|Class] lookup.
|
||||
name = key[0].name
|
||||
yield name, field
|
||||
# normal arguments (including key arguments)
|
||||
# Normal arguments (including key arguments).
|
||||
else:
|
||||
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:]
|
||||
else:
|
||||
yield None, var_arg
|
||||
@@ -601,7 +594,7 @@ class Execution(Executable):
|
||||
return self.get_params() + parsing.Scope._get_set_vars(self)
|
||||
|
||||
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)
|
||||
objects = []
|
||||
for element in attr:
|
||||
@@ -652,12 +645,11 @@ class Generator(object):
|
||||
"""
|
||||
names = []
|
||||
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.parent = self
|
||||
names.append(name)
|
||||
for n in ['close', 'throw']:
|
||||
# the name for the `next` function
|
||||
name = parsing.Name([n], 0, 0, 0)
|
||||
name.parent = None
|
||||
names.append(name)
|
||||
@@ -695,9 +687,9 @@ class Array(object):
|
||||
return [self]
|
||||
else:
|
||||
# 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:
|
||||
# multiple elements in the array
|
||||
# Multiple elements in the array.
|
||||
i = index.get_only_subelement().name
|
||||
except AttributeError:
|
||||
pass
|
||||
@@ -713,7 +705,7 @@ class Array(object):
|
||||
old_index = index
|
||||
index = None
|
||||
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:
|
||||
try:
|
||||
str_key = key_elements.get_code()
|
||||
@@ -739,7 +731,7 @@ class Array(object):
|
||||
This method generates all ArrayElements for one parsing.Array.
|
||||
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]
|
||||
names = scope.get_defined_names()
|
||||
return [ArrayElement(n) for n in names]
|
||||
@@ -769,7 +761,7 @@ class ArrayElement(object):
|
||||
self.name = name
|
||||
|
||||
def __getattr__(self, name):
|
||||
# set access rights:
|
||||
# Set access privileges:
|
||||
if name not in ['parent', 'names', 'line_nr', 'indent']:
|
||||
raise AttributeError('Strange access: %s.' % 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.
|
||||
"""
|
||||
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.
|
||||
if not position or isinstance(obj, Instance) or isinstance(obj, Function) \
|
||||
and isinstance(obj.decorated_func, Instance) \
|
||||
@@ -806,7 +798,7 @@ def get_names_for_scope(scope, position=None, star_search=True):
|
||||
start_scope = scope
|
||||
while scope:
|
||||
# `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)
|
||||
or isinstance(scope, parsing.Flow)
|
||||
or isinstance(scope, InstanceElement)
|
||||
@@ -818,13 +810,13 @@ def get_names_for_scope(scope, position=None, star_search=True):
|
||||
raise MultiLevelStopIteration('StopIteration raised somewhere')
|
||||
scope = scope.parent
|
||||
|
||||
# add star imports
|
||||
# Add star imports.
|
||||
if star_search:
|
||||
for s in remove_star_imports(start_scope.get_parent_until()):
|
||||
for g in get_names_for_scope(s, star_search=False):
|
||||
yield g
|
||||
|
||||
# add builtins to the global scope
|
||||
# Add builtins to the global scope.
|
||||
builtin_scope = builtin.Builtin.scope
|
||||
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) \
|
||||
or isinstance(r, InstanceElement) \
|
||||
and isinstance(r.var, parsing.Statement):
|
||||
# global variables handling
|
||||
# Global variables handling.
|
||||
if r.is_global():
|
||||
for token_name in r.token_list[1:]:
|
||||
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
|
||||
if isinstance(par, parsing.Flow):
|
||||
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,
|
||||
# get the types which are in the array
|
||||
# get the types which are in the array.
|
||||
arrays = follow_statement(par.inits[0])
|
||||
for array in arrays:
|
||||
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) \
|
||||
and isinstance(par.parent.parent, parsing.Class) \
|
||||
and par.position == 0:
|
||||
# this is where self gets added - this happens at another
|
||||
# place, if the var_args are clear. But some times the class is
|
||||
# This is where self gets added - this happens at another
|
||||
# place, if the var_args are clear. But sometimes the class is
|
||||
# not known. Therefore add a new instance for self. Otherwise
|
||||
# take the existing.
|
||||
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)) \
|
||||
and hasattr(par, 'get_descriptor_return'):
|
||||
try:
|
||||
#print '\n\n'
|
||||
#print name, par
|
||||
#print par.get_descriptor_return(scope)
|
||||
#raise KeyError()
|
||||
result += par.get_descriptor_return(scope)
|
||||
except KeyError:
|
||||
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
|
||||
comparison_func = lambda name: (name.line_nr, name.indent)
|
||||
for scope, name_list in scope_generator:
|
||||
#print scope, name_list[:9]
|
||||
break_scopes = []
|
||||
# here is the position stuff happening (sorting of variables)
|
||||
for name in sorted(name_list, key=comparison_func, reverse=True):
|
||||
@@ -956,7 +943,6 @@ def strip_imports(scopes):
|
||||
result = []
|
||||
for s in scopes:
|
||||
if isinstance(s, parsing.Import):
|
||||
#print 'dini mueter, steile griech!'
|
||||
try:
|
||||
result += follow_import(s)
|
||||
except modules.ModuleNotFound:
|
||||
@@ -991,20 +977,20 @@ def assign_tuples(tup, results, seek_name):
|
||||
|
||||
result = []
|
||||
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()
|
||||
result = assign_tuples(arr, results, seek_name)
|
||||
else:
|
||||
for i, t in enumerate(tup):
|
||||
# used in assignments. there is just one call and no other things,
|
||||
# therefor we can just assume, that the first part is important.
|
||||
# Used in assignments. There is just one call and no other things,
|
||||
# therefore we can just assume, that the first part is important.
|
||||
if len(t) != 1:
|
||||
raise AttributeError('Array length should be 1')
|
||||
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):
|
||||
# these are "sub" tuples
|
||||
# These are "sub"-tuples.
|
||||
result += assign_tuples(t, eval_results(i), seek_name)
|
||||
else:
|
||||
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.
|
||||
raise MultiLevelAttributeError(sys.exc_info())
|
||||
|
||||
# assignment checking is only important if the statement defines multiple
|
||||
# variables
|
||||
# Assignment checking is only important if the statement defines multiple
|
||||
# variables.
|
||||
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.
|
||||
new_result = []
|
||||
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):
|
||||
result += follow_call_list(call)
|
||||
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)):
|
||||
result.append(call)
|
||||
# The string tokens are just operations (+, -, etc.)
|
||||
elif not isinstance(call, str):
|
||||
# ternary operators
|
||||
#if str(call.name) == 'for':
|
||||
# Ternary operators.
|
||||
#if str(call.name) == 'for': <--- list comprehensions
|
||||
# print '\n\ndini mueter'
|
||||
if str(call.name) == 'if':
|
||||
while True:
|
||||
@@ -1101,16 +1087,16 @@ def follow_call(call):
|
||||
else:
|
||||
debug.warning('unknown type:', current.type, current)
|
||||
scopes = []
|
||||
# make instances of those number/string objects
|
||||
# Make instances of those number/string objects.
|
||||
scopes = [Instance(s) for s in scopes]
|
||||
else:
|
||||
# this is the first global lookup
|
||||
# This is the first global lookup.
|
||||
scopes = get_scopes_for_name(scope, current, position=position,
|
||||
search_global=True)
|
||||
result = strip_imports(scopes)
|
||||
|
||||
if result != scopes:
|
||||
# reset the position, when imports where stripped
|
||||
# Reset the position, when imports where stripped.
|
||||
position = None
|
||||
|
||||
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:
|
||||
results_new += fp
|
||||
else:
|
||||
# this means stop iteration
|
||||
# This means stop iteration.
|
||||
return results
|
||||
return results_new
|
||||
|
||||
@@ -1142,7 +1128,7 @@ def follow_path(path, scope, position=None):
|
||||
"""
|
||||
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:
|
||||
current = next(path)
|
||||
except StopIteration:
|
||||
@@ -1151,25 +1137,25 @@ def follow_path(path, scope, position=None):
|
||||
|
||||
result = []
|
||||
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:
|
||||
result = scope.get_index_types(current)
|
||||
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)
|
||||
result = Execution(scope, current).get_return_types()
|
||||
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)
|
||||
else:
|
||||
# the function must not be decorated with something else
|
||||
# The function must not be decorated with something else.
|
||||
if isinstance(scope, Function) and \
|
||||
isinstance(scope.decorated_func, Function):
|
||||
# TODO check default function methods and return them
|
||||
# TODO Check default function methods and return them.
|
||||
result = []
|
||||
else:
|
||||
# TODO check magic class methods and return them also
|
||||
# this is the typical lookup while chaining things
|
||||
# TODO Check magic class methods and return them also.
|
||||
# This is the typical lookup while chaining things.
|
||||
result = strip_imports(get_scopes_for_name(scope, current,
|
||||
position=position))
|
||||
return follow_paths(path, result, position=position)
|
||||
@@ -1181,7 +1167,7 @@ def follow_import(_import):
|
||||
:param _import: The import statement.
|
||||
:type _import: parsing.Import
|
||||
"""
|
||||
# set path together
|
||||
# Set path together.
|
||||
ns_list = []
|
||||
if _import.from_ns:
|
||||
ns_list += _import.from_ns.names
|
||||
@@ -1214,5 +1200,5 @@ def remove_star_imports(scope):
|
||||
new += remove_star_imports(m)
|
||||
modules += new
|
||||
|
||||
# filter duplicate modules
|
||||
# Filter duplicate modules.
|
||||
return set(modules)
|
||||
|
||||
Reference in New Issue
Block a user