mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-06 14:04:26 +08:00
fixed property not found bug with builtins + cleaning
This commit is contained in:
14
builtin.py
14
builtin.py
@@ -39,7 +39,6 @@ class CachedModule(object):
|
||||
|
||||
def _load_module(self):
|
||||
source = self._get_source()
|
||||
print source
|
||||
self._parser = parsing.PyFuzzyParser(source, self.path or self.name)
|
||||
p_time = None if not self.path else os.path.getmtime(self.path)
|
||||
|
||||
@@ -116,6 +115,7 @@ class Parser(CachedModule):
|
||||
should work much better for builtins.
|
||||
"""
|
||||
regex = r'^(def|class)\s+([\w\d]+)'
|
||||
|
||||
def process_code(code, depth=0):
|
||||
funcs = {}
|
||||
matches = list(re.finditer(regex, code, re.MULTILINE))
|
||||
@@ -175,12 +175,11 @@ class Parser(CachedModule):
|
||||
continue
|
||||
# this has a builtin_function_or_method
|
||||
exe = getattr(scope, n)
|
||||
#print exe, inspect.isbuiltin(exe) or inspect.ismethoddescriptor(exe)
|
||||
if inspect.isbuiltin(exe) or inspect.ismethoddescriptor(exe):
|
||||
funcs[n] = exe
|
||||
elif type(exe) == type:
|
||||
elif inspect.isclass(exe):
|
||||
classes[n] = exe
|
||||
elif type(exe).__name__ == 'member_descriptor':
|
||||
elif inspect.ismemberdescriptor(exe):
|
||||
members[n] = exe
|
||||
else:
|
||||
stmts[n] = exe
|
||||
@@ -237,10 +236,11 @@ class Parser(CachedModule):
|
||||
|
||||
# class members (functions) properties?
|
||||
for name, func in members.items():
|
||||
# recursion problem in properties TODO remove
|
||||
if name in ['fget', 'fset', 'fdel']: continue
|
||||
ret = 'pass'
|
||||
code += '@property\ndef %s(self):\n' % (name)
|
||||
block = get_doc(func, indent=True) + '%s\n\n' % ret
|
||||
code += parsing.indent_block(block)
|
||||
code += parsing.indent_block(get_doc(func) + '%s\n\n' % ret)
|
||||
|
||||
# variables
|
||||
for name, value in stmts.items():
|
||||
@@ -328,7 +328,7 @@ class _Builtin(object):
|
||||
if sys.hexversion >= 0x03000000:
|
||||
name = 'builtins'
|
||||
else:
|
||||
name='__builtin__'
|
||||
name = '__builtin__'
|
||||
_builtins = Parser(name=name)
|
||||
|
||||
@property
|
||||
|
||||
29
evaluate.py
29
evaluate.py
@@ -5,7 +5,8 @@ follow_statement -> follow_call -> follow_paths -> follow_path
|
||||
`get_names_for_scope` and `get_scopes_for_name` are search functions
|
||||
|
||||
TODO doc
|
||||
TODO list comprehensions, priority?
|
||||
TODO list comprehensions, priority? +1
|
||||
TODO `a = b if b else None` expressions
|
||||
TODO evaluate asserts (type safety)
|
||||
|
||||
python 3 stuff:
|
||||
@@ -14,9 +15,10 @@ TODO annotations ? how ? type evaluation and return?
|
||||
TODO nonlocal statement
|
||||
|
||||
TODO getattr / __getattr__ / __getattribute__ ?
|
||||
|
||||
TODO descriptors (also for classes, for instances it should work)
|
||||
TODO @staticmethod @classmethod (implement descriptors, builtins are done)
|
||||
TODO variable assignments in classes (see test/completion/classes @230)
|
||||
TODO variable assignments in classes (see test/completion/classes @230) +1
|
||||
"""
|
||||
from _compatibility import next, property
|
||||
import sys
|
||||
@@ -219,7 +221,6 @@ class InstanceElement(object):
|
||||
par = InstanceElement(self.instance, par)
|
||||
return par
|
||||
|
||||
|
||||
def get_parent_until(self, *classes):
|
||||
scope = self.var.get_parent_until(*classes)
|
||||
return InstanceElement(self.instance, scope)
|
||||
@@ -233,6 +234,7 @@ class InstanceElement(object):
|
||||
|
||||
class Class(object):
|
||||
__metaclass__ = CachedMetaClass
|
||||
|
||||
def __init__(self, base):
|
||||
self.base = base
|
||||
|
||||
@@ -288,6 +290,7 @@ class Function(object):
|
||||
"""
|
||||
"""
|
||||
__metaclass__ = CachedMetaClass
|
||||
|
||||
def __init__(self, func, is_decorated=False):
|
||||
""" This should not be called directly """
|
||||
self.base_func = func
|
||||
@@ -330,7 +333,7 @@ class Function(object):
|
||||
# this is here, that the wrapper gets executed
|
||||
f = wrappers[0]
|
||||
|
||||
debug.dbg('decorator end')
|
||||
debug.dbg('decorator end', f)
|
||||
if f != self.base_func and isinstance(f, parsing.Function):
|
||||
f = Function(f)
|
||||
return f
|
||||
@@ -564,12 +567,6 @@ class Execution(Executable):
|
||||
Call the default method with the own instance (self implements all
|
||||
the necessary functions). Add also the params.
|
||||
"""
|
||||
# result = self.get_params() + parsing.Scope._get_set_vars(self)
|
||||
# print '\n\ndef', result, 'par', self, self.parent
|
||||
# print 'set', parsing.Scope._get_set_vars(self)
|
||||
# print 'set', [r.parent for r in parsing.Scope._get_set_vars(self)]
|
||||
# print 'para', [r.parent.parent for r in self.get_params()]
|
||||
# return result
|
||||
return self.get_params() + parsing.Scope._get_set_vars(self)
|
||||
|
||||
@property
|
||||
@@ -599,7 +596,7 @@ class Execution(Executable):
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name not in ['indent', 'line_nr', 'imports']:
|
||||
raise AttributeError('Tried to access %s. Why?' % name)
|
||||
raise AttributeError('Tried to access %s: %s. Why?' % (name, self))
|
||||
return getattr(self.base, name)
|
||||
|
||||
@property
|
||||
@@ -755,14 +752,15 @@ class ArrayElement(object):
|
||||
return "<%s of %s>" % (self.__class__.__name__, self.name)
|
||||
|
||||
|
||||
def get_defined_names_for_position(obj, position=(float('inf'), float('inf'))):
|
||||
def get_defined_names_for_position(obj, position=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,
|
||||
# because class variables are always valid and the `self.` variables, too.
|
||||
if not position or isinstance(obj, Instance):
|
||||
if not position or isinstance(obj, Instance) or isinstance(obj, Function) \
|
||||
and isinstance(obj.decorated_func, Instance):
|
||||
return names
|
||||
names_new = []
|
||||
for n in names:
|
||||
@@ -907,10 +905,7 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False):
|
||||
if search_global:
|
||||
scope_generator = get_names_for_scope(scope, position=position)
|
||||
else:
|
||||
if position:
|
||||
names = get_defined_names_for_position(scope, position)
|
||||
else:
|
||||
names = scope.get_defined_names()
|
||||
names = get_defined_names_for_position(scope, position)
|
||||
scope_generator = iter([(scope, names)])
|
||||
|
||||
return remove_statements(filter_name(scope_generator))
|
||||
|
||||
@@ -43,9 +43,9 @@ class staticmethod():
|
||||
|
||||
class classmethod():
|
||||
def __init__(self, func):
|
||||
self.func = func
|
||||
self._func = func
|
||||
|
||||
def __get__(self, obj, cls):
|
||||
def method(*args, **kwargs):
|
||||
self.func(cls, *args, **kwargs)
|
||||
return method
|
||||
def _method(*args, **kwargs):
|
||||
self._func(cls, *args, **kwargs)
|
||||
return _method
|
||||
|
||||
@@ -150,36 +150,9 @@ CallClass()()
|
||||
# -----------------
|
||||
# properties
|
||||
# -----------------
|
||||
class Property():
|
||||
def __init__(self, fget, fset = None, fdel = None, doc = None):
|
||||
self.fget = fget
|
||||
self.fset = fset
|
||||
self.fdel = fdel
|
||||
self.__doc__ = doc
|
||||
|
||||
def __get__(self, obj, cls):
|
||||
return self.fget(obj)
|
||||
|
||||
def __set__(self, obj, value):
|
||||
self.fset(obj, value)
|
||||
|
||||
def __delete__(self, obj):
|
||||
self.fdel(obj)
|
||||
|
||||
def setter(self, func):
|
||||
self.fset = func
|
||||
return self
|
||||
|
||||
def getter(self, func):
|
||||
self.fget = func
|
||||
return self
|
||||
|
||||
def deleter(self, func):
|
||||
self.fdel = func
|
||||
return self
|
||||
|
||||
class B():
|
||||
@Property
|
||||
@property
|
||||
def r(self):
|
||||
return 1
|
||||
@r.setter
|
||||
@@ -187,7 +160,7 @@ class B():
|
||||
pass
|
||||
def t(self):
|
||||
return ''
|
||||
p = Property(t)
|
||||
##p = property(t)
|
||||
|
||||
#? []
|
||||
B().r()
|
||||
|
||||
@@ -22,12 +22,11 @@ def run_completion_test(correct, source, line_nr, line):
|
||||
try:
|
||||
completions = functions.complete(source, line_nr, 999,
|
||||
completion_test_dir)
|
||||
except Exception:
|
||||
except (Exception, functions.evaluate.MultiLevelAttributeError):
|
||||
print('test @%s: %s' % (line_nr-1, line))
|
||||
print(traceback.format_exc())
|
||||
return 1
|
||||
else:
|
||||
# TODO remove sorted? completions should be sorted?
|
||||
# TODO remove set! duplicates should not be normal
|
||||
comp_str = str(sorted(set([str(c) for c in completions])))
|
||||
if comp_str != correct:
|
||||
@@ -47,7 +46,7 @@ def run_definition_test(correct, source, line_nr, line, correct_start):
|
||||
completion_test_dir))
|
||||
try:
|
||||
result = defs(line_nr, 999)
|
||||
except Exception:
|
||||
except (Exception, functions.evaluate.MultiLevelAttributeError):
|
||||
print('test @%s: %s' % (line_nr-1, line))
|
||||
print(traceback.format_exc())
|
||||
return 1
|
||||
|
||||
Reference in New Issue
Block a user