[pypy-svn] r18755 - in pypy/dist/pypy/rpython/ootypesystem: . test

arigo at codespeak.net arigo at codespeak.net
Wed Oct 19 17:03:38 CEST 2005


Author: arigo
Date: Wed Oct 19 17:03:38 2005
New Revision: 18755

Modified:
   pypy/dist/pypy/rpython/ootypesystem/rclass.py
   pypy/dist/pypy/rpython/ootypesystem/test/test_ooclean.py
Log:
fix bug with methods and class attributes not being found
if present in a superclass but used from a subclass.


Modified: pypy/dist/pypy/rpython/ootypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rclass.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rclass.py	Wed Oct 19 17:03:38 2005
@@ -1,5 +1,5 @@
 import types
-from pypy.rpython.rmodel import inputconst
+from pypy.rpython.rmodel import inputconst, TyperError
 from pypy.rpython.rclass import AbstractClassRepr, AbstractInstanceRepr, \
                                 getinstancerepr, getclassrepr, get_type_repr
 from pypy.rpython.rpbc import getsignature
@@ -95,11 +95,24 @@
             for name, attrdef in attrs:
                 if not attrdef.readonly:
                     continue
-                try:
-                    impl = self.classdef.cls.__dict__[name]
-                except KeyError:
-                    continue
                 mangled = mangle(name)
+                if mangled in allmethods or mangled in allclassattributes:
+                    # if the method/attr was already found in a parent class,
+                    # we register it again only if it is overridden.
+                    if name not in self.classdef.cls.__dict__:
+                        continue
+                    impl = self.classdef.cls.__dict__[name]
+                else:
+                    # otherwise, for new method/attrs, we look in all parent
+                    # classes to see if it's defined in a parent but only
+                    # actually first used in self.classdef.
+                    for clsdef in self.classdef.getmro():
+                        if name in clsdef.cls.__dict__:
+                            impl = clsdef.cls.__dict__[name]
+                            break
+                    else:
+                        raise TyperError("class %r has no attribute %r" % (
+                            self.classdef.cls, name))
                 if classrepr.prepare_method(attrdef.s_value) is not None:
                     # a regular method
                     f, inputs, ret = getsignature(self.rtyper, impl)

Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_ooclean.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_ooclean.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_ooclean.py	Wed Oct 19 17:03:38 2005
@@ -118,6 +118,18 @@
     result = interpret(dummyfn, [False], type_system='ootype')
     assert result == 2
 
+def test_method_used_in_subclasses_only():
+    class A:
+        def meth(self):
+            return 123
+    class B(A):
+        pass
+    def f():
+        x = B()
+        return x.meth()
+    res = interpret(f, [], type_system='ootype')
+    assert res == 123
+
 class HasAField(object):
     def f(self):
         return self.a
@@ -189,6 +201,26 @@
     res = interpret(dummyfn, [], type_system='ootype')
     assert res == 4
 
+def test_classattr_used_in_subclasses_only():
+    class Subclass1(HasClassAttr):
+        pass
+    class Subclass2(HasClassAttr):
+        pass
+    class SubSubclass2(Subclass2):
+        a = 5432
+    def dummyfn(flag):
+        inst1 = Subclass1()
+        inst1.a += 42         # used as default
+        if flag:
+            inst2 = Subclass2()
+        else:
+            inst2 = SubSubclass2()
+        return inst1.a + inst2.a
+    res = interpret(dummyfn, [True], type_system='ootype')
+    assert res == (3 + 42) + 3
+    res = interpret(dummyfn, [False], type_system='ootype')
+    assert res == (3 + 42) + 5432
+
 def test_name_clashes():
     class NameClash1(object):
         def _TYPE(self):



More information about the Pypy-commit mailing list