fixed property not found bug with builtins + cleaning

This commit is contained in:
David Halter
2012-06-24 18:47:57 +02:00
parent 548af3cc86
commit 3650e0ee64
5 changed files with 27 additions and 60 deletions

View File

@@ -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

View File

@@ -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))

View File

@@ -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

View File

@@ -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()

View File

@@ -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