mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-08 06:44:46 +08:00
temporary commit: introduced MultiLevelAttributeError. many prints to remove
This commit is contained in:
141
evaluate.py
141
evaluate.py
@@ -28,6 +28,8 @@ import debug
|
|||||||
import builtin
|
import builtin
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import sys, traceback
|
||||||
memoize_caches = []
|
memoize_caches = []
|
||||||
|
|
||||||
|
|
||||||
@@ -35,6 +37,23 @@ class MultiLevelStopIteration(Exception):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class MultiLevelAttributeError(BaseException):
|
||||||
|
"""
|
||||||
|
Important, because `__getattr__` and `hasattr` catch AttributeErrors
|
||||||
|
implicitly. This is really evil (mainly because of `__getattr__`).
|
||||||
|
`hasattr` in Python 2 is even more evil, because it catches ALL exceptions.
|
||||||
|
Therefore this class has to be `BaseException` and not `Exception`.
|
||||||
|
"""
|
||||||
|
def __init__(self, base):
|
||||||
|
self.base = base
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '%s: %s' % (self.base.__class__.__name__, self.base)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.__repr__()
|
||||||
|
|
||||||
|
|
||||||
def clear_caches():
|
def clear_caches():
|
||||||
for m in memoize_caches:
|
for m in memoize_caches:
|
||||||
m.clear()
|
m.clear()
|
||||||
@@ -164,17 +183,32 @@ class Instance(Executable):
|
|||||||
|
|
||||||
return names
|
return names
|
||||||
|
|
||||||
@property
|
def get_descriptor_return(self, obj):
|
||||||
def line_nr(self):
|
""" Throws an error if there's no method. """
|
||||||
return self.base.line_nr
|
print '\n\nis_desc'
|
||||||
|
method = self.get_subscope_by_name('__get__')
|
||||||
|
print 'yessa'
|
||||||
|
# args in __set__ descriptors are obj, class.
|
||||||
|
args = [[obj], [obj.base]]
|
||||||
|
method = InstanceElement(self, method)
|
||||||
|
print 'la'
|
||||||
|
try:
|
||||||
|
res = Execution(method, args).get_return_types()
|
||||||
|
except Exception,e :
|
||||||
|
traceback.print_stack(file=sys.stdout)
|
||||||
|
print e, type(e)
|
||||||
|
print '\n'
|
||||||
|
#raise AttributeError('dini mueter')
|
||||||
|
raise e
|
||||||
|
|
||||||
@property
|
print res
|
||||||
def indent(self):
|
print '\n\n'
|
||||||
return self.base.indent
|
return res
|
||||||
|
|
||||||
@property
|
def __getattr__(self, name):
|
||||||
def name(self):
|
if name not in ['line_nr', 'indent', 'name']:
|
||||||
return self.base.name
|
raise AttributeError("Don't touch this (%s)!" % name)
|
||||||
|
return getattr(self.base, name)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<e%s of %s (var_args: %s)>" % \
|
return "<e%s of %s (var_args: %s)>" % \
|
||||||
@@ -190,17 +224,36 @@ class InstanceElement(object):
|
|||||||
@property
|
@property
|
||||||
@memoize_default()
|
@memoize_default()
|
||||||
def parent(self):
|
def parent(self):
|
||||||
par = self.var.parent
|
try:
|
||||||
if isinstance(par, parsing.Function):
|
par = self.var.parent
|
||||||
par = Function(par)
|
if isinstance(par, parsing.Function):
|
||||||
return InstanceElement(self.instance, par)
|
par = Function(par)
|
||||||
|
return InstanceElement(self.instance, par)
|
||||||
|
except Exception, e:
|
||||||
|
traceback.print_stack(file=sys.stdout)
|
||||||
|
print e
|
||||||
|
print '\n'
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
def get_parent_until(self, *classes):
|
def get_parent_until(self, *classes):
|
||||||
scope = self.var.get_parent_until(*classes)
|
scope = self.var.get_parent_until(*classes)
|
||||||
return InstanceElement(self.instance, scope)
|
return InstanceElement(self.instance, scope)
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattribute__(self, name):
|
||||||
return getattr(self.var, name)
|
try:
|
||||||
|
a = object.__getattribute__(self, name)
|
||||||
|
except AttributeError:
|
||||||
|
try:
|
||||||
|
return getattr(self.var, name)
|
||||||
|
except AttributeError:
|
||||||
|
if name == '__get__':
|
||||||
|
raise
|
||||||
|
raise MultiLevelAttributeError(sys.exc_info()[1])
|
||||||
|
else:
|
||||||
|
if hasattr(a, '__get__'):
|
||||||
|
return a.__get__(self, self.__class__)
|
||||||
|
return a
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<%s of %s>" % (self.__class__.__name__, self.var)
|
return "<%s of %s>" % (self.__class__.__name__, self.var)
|
||||||
@@ -268,9 +321,8 @@ class Function(object):
|
|||||||
self.base_func = func
|
self.base_func = func
|
||||||
self.is_decorated = is_decorated
|
self.is_decorated = is_decorated
|
||||||
|
|
||||||
@property
|
|
||||||
@memoize_default()
|
@memoize_default()
|
||||||
def func(self):
|
def decorated_func(self):
|
||||||
"""
|
"""
|
||||||
Returns the function, that is to be executed in the end.
|
Returns the function, that is to be executed in the end.
|
||||||
This is also the places where the decorators are processed.
|
This is also the places where the decorators are processed.
|
||||||
@@ -283,7 +335,7 @@ class Function(object):
|
|||||||
debug.dbg('decorator:', dec, f)
|
debug.dbg('decorator:', dec, f)
|
||||||
dec_results = follow_statement(dec)
|
dec_results = follow_statement(dec)
|
||||||
if not len(dec_results):
|
if not len(dec_results):
|
||||||
debug.warning('decorator func not found: %s in stmt %s' %
|
debug.warning('decorator func not found: %s in stmt %s' %
|
||||||
(self.base_func, dec))
|
(self.base_func, dec))
|
||||||
return None
|
return None
|
||||||
if len(dec_results) > 1:
|
if len(dec_results) > 1:
|
||||||
@@ -294,6 +346,13 @@ class Function(object):
|
|||||||
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]]
|
||||||
|
try:
|
||||||
|
wrappers = Execution(decorator, params).get_return_types()
|
||||||
|
except Exception, e:
|
||||||
|
traceback.print_stack(file=sys.stdout)
|
||||||
|
print e
|
||||||
|
print '\n'
|
||||||
|
raise
|
||||||
wrappers = Execution(decorator, params).get_return_types()
|
wrappers = Execution(decorator, params).get_return_types()
|
||||||
if not len(wrappers):
|
if not len(wrappers):
|
||||||
debug.warning('no wrappers found', self.base_func)
|
debug.warning('no wrappers found', self.base_func)
|
||||||
@@ -309,8 +368,20 @@ class Function(object):
|
|||||||
f = Function(f)
|
f = Function(f)
|
||||||
return f
|
return f
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattribute__(self, name):
|
||||||
return getattr(self.func, name)
|
try:
|
||||||
|
a = object.__getattribute__(self, name)
|
||||||
|
except AttributeError:
|
||||||
|
try:
|
||||||
|
return getattr(self.decorated_func(), name)
|
||||||
|
except AttributeError:
|
||||||
|
if name == '__get__':
|
||||||
|
raise
|
||||||
|
raise MultiLevelAttributeError(sys.exc_info()[1])
|
||||||
|
else:
|
||||||
|
if hasattr(a, '__get__'):
|
||||||
|
return a.__get__(self, self.__class__)
|
||||||
|
return a
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<e%s of %s>" % (self.__class__.__name__, self.base_func)
|
return "<e%s of %s>" % (self.__class__.__name__, self.base_func)
|
||||||
@@ -337,7 +408,7 @@ class Execution(Executable):
|
|||||||
# 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 Execution(self.base.func).get_return_types(True)
|
return Execution(self.base.decorated_func()).get_return_types(True)
|
||||||
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.
|
||||||
@@ -348,12 +419,13 @@ class Execution(Executable):
|
|||||||
# 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):
|
except (AttributeError, KeyError):
|
||||||
|
print '\n\n\n\n\n\nfuuuuuuu'
|
||||||
debug.warning("no execution possible", self.base)
|
debug.warning("no execution possible", self.base)
|
||||||
else:
|
else:
|
||||||
debug.dbg('__call__', call_method, self.base)
|
debug.dbg('__call__', call_method, self.base)
|
||||||
base = self.base
|
base = self.base
|
||||||
if isinstance(self.base, Function):
|
if isinstance(self.base, Function):
|
||||||
base = self.base.func
|
base = self.base.decorated_func()
|
||||||
call_method = InstanceElement(base, call_method)
|
call_method = InstanceElement(base, call_method)
|
||||||
exe = Execution(call_method, self.var_args)
|
exe = Execution(call_method, self.var_args)
|
||||||
stmts = exe.get_return_types()
|
stmts = exe.get_return_types()
|
||||||
@@ -551,6 +623,7 @@ class Execution(Executable):
|
|||||||
try:
|
try:
|
||||||
return call.parent_stmt.parent
|
return call.parent_stmt.parent
|
||||||
except AttributeError: # if operators are there
|
except AttributeError: # if operators are there
|
||||||
|
print '\n\n\n\n\n\nfuuuuuuu'
|
||||||
pass
|
pass
|
||||||
raise IndexError('No params available')
|
raise IndexError('No params available')
|
||||||
|
|
||||||
@@ -647,6 +720,7 @@ class Array(object):
|
|||||||
# 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:
|
||||||
|
print '\n\n\n\n\n\nfuuuuuuu'
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
@@ -665,9 +739,11 @@ class Array(object):
|
|||||||
try:
|
try:
|
||||||
str_key = key_elements.get_code()
|
str_key = key_elements.get_code()
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
|
print '\n\n\n\n\n\nfuuuuuuu'
|
||||||
try:
|
try:
|
||||||
str_key = key_elements[0].name
|
str_key = key_elements[0].name
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
|
print '\n\n\n\n\n\nfuuuuuuu'
|
||||||
str_key = None
|
str_key = None
|
||||||
if old_index == str_key:
|
if old_index == str_key:
|
||||||
index = i
|
index = i
|
||||||
@@ -836,6 +912,13 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False):
|
|||||||
else:
|
else:
|
||||||
inst = Instance(Class(par.parent.parent))
|
inst = Instance(Class(par.parent.parent))
|
||||||
result.append(inst)
|
result.append(inst)
|
||||||
|
elif isinstance(par, Instance) \
|
||||||
|
and hasattr(par, 'get_descriptor_return'):
|
||||||
|
try:
|
||||||
|
result += par.get_descriptor_return(scope)
|
||||||
|
except KeyError:
|
||||||
|
result.append(par)
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
result.append(par)
|
result.append(par)
|
||||||
return result
|
return result
|
||||||
@@ -852,6 +935,10 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False):
|
|||||||
s = scope.base if isinstance(scope, Class) else scope
|
s = scope.base if isinstance(scope, Class) else scope
|
||||||
# this means that a definition was found and is not e.g.
|
# this means that a definition was found and is not e.g.
|
||||||
# in if/else.
|
# in if/else.
|
||||||
|
print 'dini mueter1', name, name.parent, result
|
||||||
|
a = name.parent.parent
|
||||||
|
print 'dini mueter2', a
|
||||||
|
print 'end dini m'
|
||||||
if not name.parent or name.parent.parent == s:
|
if not name.parent or name.parent.parent == s:
|
||||||
break
|
break
|
||||||
# if there are results, ignore the other scopes
|
# if there are results, ignore the other scopes
|
||||||
@@ -948,7 +1035,12 @@ def follow_statement(stmt, scope=None, seek_name=None):
|
|||||||
debug.dbg('follow_stmt %s in %s (%s)' % (stmt, scope, seek_name))
|
debug.dbg('follow_stmt %s in %s (%s)' % (stmt, scope, seek_name))
|
||||||
call_list = stmt.get_assignment_calls()
|
call_list = stmt.get_assignment_calls()
|
||||||
debug.dbg('calls: %s' % call_list)
|
debug.dbg('calls: %s' % call_list)
|
||||||
result = follow_call_list(scope, call_list)
|
|
||||||
|
try:
|
||||||
|
result = follow_call_list(scope, call_list)
|
||||||
|
except AttributeError:
|
||||||
|
# This is so evil! But necessary to propagate errors.
|
||||||
|
raise MultiLevelAttributeError(sys.exc_info()[1])
|
||||||
|
|
||||||
# assignment checking is only important if the statement defines multiple
|
# assignment checking is only important if the statement defines multiple
|
||||||
# variables
|
# variables
|
||||||
@@ -1067,7 +1159,8 @@ def follow_path(path, scope, position=None):
|
|||||||
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 isinstance(scope.func, Function):
|
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 = []
|
result = []
|
||||||
print 'la'
|
print 'la'
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ CallClass()()
|
|||||||
# -----------------
|
# -----------------
|
||||||
# properties
|
# properties
|
||||||
# -----------------
|
# -----------------
|
||||||
class Property(object):
|
class Property():
|
||||||
def __init__(self, fget, fset = None, fdel = None, doc = None):
|
def __init__(self, fget, fset = None, fdel = None, doc = None):
|
||||||
self.fget = fget
|
self.fget = fget
|
||||||
self.fset = fset
|
self.fset = fset
|
||||||
|
|||||||
Reference in New Issue
Block a user