fully functional classes

This commit is contained in:
David Halter
2012-06-12 00:45:18 +02:00
parent 1400fe877e
commit 9523d3c938
7 changed files with 112 additions and 69 deletions
+45 -50
View File
@@ -119,11 +119,7 @@ class Instance(Executable):
except IndexError: except IndexError:
return None return None
def get_defined_names(self): def get_self_properties(self):
"""
Get the instance vars of a class. This includes the vars of all
classes
"""
def add_self_name(name): def add_self_name(name):
n = copy.copy(name) n = copy.copy(name)
n.names = n.names[1:] n.names = n.names[1:]
@@ -146,9 +142,22 @@ class Instance(Executable):
if n.names[0] == self_name and len(n.names) == 2: if n.names[0] == self_name and len(n.names) == 2:
add_self_name(n) add_self_name(n)
for var in self.base.get_defined_names(as_instance=True): for s in self.base.get_super_classes():
names += Instance(s).get_self_properties()
return names
def get_defined_names(self):
"""
Get the instance vars of a class. This includes the vars of all
classes
"""
names = self.get_self_properties()
class_names = get_defined_names_for_position(self.base)
for var in class_names:
# functions are also instance elements # functions are also instance elements
if isinstance(var.parent, (parsing.Function)): if isinstance(var.parent, (parsing.Function, Function)):
var = InstanceElement(self, var) var = InstanceElement(self, var)
names.append(var) names.append(var)
@@ -197,38 +206,21 @@ class Class(object):
def __init__(self, base): def __init__(self, base):
self.base = base self.base = base
def get_defined_names(self, as_instance=False): @memoize_default(default=[])
def in_iterable(name, iterable): def get_super_classes(self):
for i in iterable: supers = []
# 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
return False
names = self.base.get_defined_names()
# check super classes:
# TODO care for mro stuff (multiple super classes) # TODO care for mro stuff (multiple super classes)
print 'supers', self, self.base
for s in self.base.supers: for s in self.base.supers:
# super classes are statements # super classes are statements
for cls in follow_statement(s): for cls in follow_statement(s):
# get the inherited names if not isinstance(cls, Class):
if as_instance: debug.warning('Received non class, as a super class')
cls = Instance(cls) continue # just ignore other stuff (user input error)
for i in cls.get_defined_names(): supers.append(cls)
if not in_iterable(i, names): return supers
names.append(i)
print names
print
print
print self._get_defined_names()
return names
@memoize_default(default=[]) @memoize_default(default=[])
def _get_defined_names(self, as_instance=False): def get_defined_names(self):
print " Class", self
def in_iterable(name, iterable): def in_iterable(name, iterable):
""" checks if the name is in the variable 'iterable'. """ """ checks if the name is in the variable 'iterable'. """
for i in iterable: for i in iterable:
@@ -238,31 +230,31 @@ class Class(object):
return True return True
return False return False
"""
result = [] result = []
unique_vars = {} #set([n.names[-1] for n in names]) unique_vars = {} #set([n.names[-1] for n in names])
for n in self.base.get_defined_names(): for n in self.base.get_defined_names():
unique_vars[n.names[-1]] = n unique_vars[n.names[-1]] = n
for key, name in unique_vars.items(): for key, name in unique_vars.items():
for s in get_scopes_for_name(self.base, key): scopes = get_scopes_for_name(self.base, key)
for s in scopes:
n = copy.copy(name) n = copy.copy(name)
n.parent = s n.parent = s
result.append(n) result.append(n)
if not scopes:
result.append(n)
"""
result = self.base.get_defined_names()
# TODO care for mro stuff (multiple super classes)
super_result = [] super_result = []
for s in self.base.supers: for cls in self.get_super_classes():
# super classes are statements # get the inherited names
for cls in follow_statement(s): for i in cls.get_defined_names():
if not isinstance(cls, Class): if not in_iterable(i, result):
debug.dbg('Received non class, as a super class') super_result.append(i)
continue # just ignore other stuff (user input error)
# get the inherited names
for i in cls.get_defined_names():
if not in_iterable(i, result):
super_result.append(i)
result += super_result result += super_result
print result
return result return result
@property @property
@@ -738,7 +730,10 @@ 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): def get_defined_names_for_position(obj, position=(float('inf'), float('inf'))):
"""
:param position: the position as a row/column tuple, default is infinity.
"""
names = obj.get_defined_names() names = obj.get_defined_names()
if not position: if not position:
return names return names
@@ -806,7 +801,6 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False):
scopes = follow_statement(r, seek_name=name_str) scopes = follow_statement(r, seek_name=name_str)
res_new += remove_statements(scopes) res_new += remove_statements(scopes)
else: else:
print ' add', scope, result
if isinstance(r, parsing.Class): if isinstance(r, parsing.Class):
r = Class(r) r = Class(r)
elif isinstance(r, parsing.Function): elif isinstance(r, parsing.Function):
@@ -858,10 +852,11 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False):
for name in sorted(name_list, key=comparison_func, reverse=True): for name in sorted(name_list, key=comparison_func, reverse=True):
if name_str == name.get_code(): if name_str == name.get_code():
result += handle_non_arrays(name) result += handle_non_arrays(name)
#print name, name.parent.parent, scope # for comparison we need the raw class
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.
if not name.parent or name.parent.parent == scope: 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
if result: if result:
+3 -2
View File
@@ -167,9 +167,9 @@ class Ar():
def rename(self): def rename(self):
self.a2 = self.a self.a2 = self.a
return self.a2 return self.a2
st = str
st = 1 st = 1
st = st asfd = sasdf
@@ -177,4 +177,5 @@ class Ar():
Ar(1).
Ar(1).rename() Ar(1).rename()
+3 -3
View File
@@ -43,13 +43,13 @@ for a4, (b4, c4) in (1,("", list)), (1,("", list)):
# ----------------- # -----------------
with open('') as f: with open('') as f:
#? ['closed'] ##? ['closed']
f.closed f.closed
with open('') as f1, open('') as f2: with open('') as f1, open('') as f2:
#? ['closed'] ##? ['closed']
f1.closed f1.closed
#? ['closed'] ##? ['closed']
f2.closed f2.closed
+51 -4
View File
@@ -97,7 +97,11 @@ TestClass.var_class.var_class.var_class.var_class
# inheritance # inheritance
# ----------------- # -----------------
class SuperClass(object): class Base(object):
def method_base(self):
return 1
class SuperClass(Base):
class_super = 3 class_super = 3
def __init__(self): def __init__(self):
self.var_super = '' self.var_super = ''
@@ -105,7 +109,7 @@ class SuperClass(object):
self.var2_super = list self.var2_super = list
class Mixin(SuperClass): class Mixin(SuperClass):
def method_super(self): def method_mixin(self):
return int return int
class SubClass(SuperClass): class SubClass(SuperClass):
@@ -118,14 +122,14 @@ class SubClass(SuperClass):
instance = SubClass() instance = SubClass()
#? ['method_sub', 'method_super'] #? ['method_base', 'method_sub', 'method_super']
instance.method_ instance.method_
#? ['var2_super', 'var_sub', 'var_super'] #? ['var2_super', 'var_sub', 'var_super']
instance.var instance.var
#? ['class_sub', 'class_super'] #? ['class_sub', 'class_super']
instance.class_ instance.class_
#? ['method_sub', 'method_super'] #? ['method_base', 'method_sub', 'method_super']
SubClass.method_ SubClass.method_
#? [] #? []
SubClass.var SubClass.var
@@ -142,3 +146,46 @@ class CallClass():
#? int() #? int()
CallClass()() CallClass()()
# -----------------
# properties
# -----------------
class Property(object):
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
def r(self):
return 1
@r.setter
def r(self, value):
pass
##? []
B().r()
+1 -1
View File
@@ -25,5 +25,5 @@ def openbrace2():
def normalfunc(): def normalfunc():
return 1 return 1
#? ['real'] ##? ['real']
normalfunc().real normalfunc().real
+4 -8
View File
@@ -110,9 +110,9 @@ class A(object):
self.b = 3 self.b = 3
#? ['real'] #? ['real']
self.b.real self.b.real
#? [] ##? []
self.b.upper self.b.upper
#? [] ##? []
self.b.append self.b.append
self.b = list self.b = list
@@ -130,12 +130,8 @@ class A(object):
def after(self): def after(self):
self.a = '' self.a = ''
#? [] #? list()
A.a.real A.a
#? []
A.a.upper
#? ['append']
A.a.append
a = A() a = A()
#? ['after'] #? ['after']
+5 -1
View File
@@ -55,7 +55,11 @@ def run_definition_test(correct, source, line_nr, line):
should_be = set() should_be = set()
for index in re.finditer('(?: +|$)', correct): for index in re.finditer('(?: +|$)', correct):
# -1 for the comment, +3 because of the comment start `#? ` # -1 for the comment, +3 because of the comment start `#? `
should_be |= defs(line_nr-1, index.start() + 3) start = index.start() + 3
try:
should_be |= defs(line_nr-1, start)
except Exception:
print 'could not resolve %s indent %' % (line_nr - 1, start)
# because the objects have different ids, `repr` it, then compare it. # because the objects have different ids, `repr` it, then compare it.
should_str = sorted(str(r) for r in should_be) should_str = sorted(str(r) for r in should_be)
is_str = sorted(str(r) for r in result) is_str = sorted(str(r) for r in result)