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