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

arigo at codespeak.net arigo at codespeak.net
Thu Oct 20 11:47:19 CEST 2005


Author: arigo
Date: Thu Oct 20 11:47:18 2005
New Revision: 18787

Modified:
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/ootypesystem/rclass.py
   pypy/dist/pypy/rpython/ootypesystem/test/test_ooclean.py
Log:
ootyper: abstract base methods


Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Thu Oct 20 11:47:18 2005
@@ -73,10 +73,11 @@
         # _add_fields adds *descriptions* of fields.  This is obvious
         # if you are in the right state of mind (swiss?), but
         # certainly not necessarily if not.
+        # NB. a None method is a purely abstract one.
         for name, method in methods.iteritems():
             if self._has_field(name):
                 raise TypeError("Can't add method %r: field already exists" % name)
-            if not isinstance(typeOf(method), Meth):
+            if method is not None and not isinstance(typeOf(method), Meth):
                 raise TypeError("added methods must be _meths, not %s" % type(defn))
         self._methods.update(methods)
 

Modified: pypy/dist/pypy/rpython/ootypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rclass.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rclass.py	Thu Oct 20 11:47:18 2005
@@ -123,9 +123,15 @@
                 if not attrdef.readonly:
                     continue
                 mangled = mangle(name)
+                is_method = (classrepr.prepare_method(attrdef.s_value)
+                             is not None)
                 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 is_method and mangled in allclassattributes:
+                        raise TyperError("method overrides class attribute")
+                    if not is_method and mangled in allmethods:
+                        raise TyperError("class attribute overrides method")
                     if name not in self.classdef.cls.__dict__:
                         continue
                     impl = self.classdef.cls.__dict__[name]
@@ -138,14 +144,21 @@
                             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:
+                        if is_method:
+                            impl = None    # abstract base method
+                        else:
+                            raise TyperError("class %r has no attribute %r" % (
+                                self.classdef.cls, name))
+                if is_method:
                     # a regular method
-                    f, inputs, ret = getsignature(self.rtyper, impl)
+                    exmpl = impl or attrdef.s_value.prebuiltinstances.keys()[0]
+                    f, inputs, ret = getsignature(self.rtyper, exmpl)
                     M = ootype.Meth([r.lowleveltype for r in inputs[1:]], ret.lowleveltype)
-                    m = ootype.meth(M, _name=mangled, _callable=impl,
-                                    graph=f.graph)
+                    if impl:
+                        m = ootype.meth(M, _name=mangled, _callable=impl,
+                                        graph=f.graph)
+                    else:
+                        m = None
                     methods[mangled] = m
                     allmethods[mangled] = True
                 else:

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	Thu Oct 20 11:47:18 2005
@@ -491,3 +491,23 @@
         return e.attr()
     res = interpret(f, [])
     assert res == 42
+
+def test_abstract_base_method():
+    class A(object):
+        pass
+    class B(A):
+        def f(self):
+            return 2
+    class C(A):
+        def f(self):
+            return 3
+    def f(flag):
+        if flag:
+            x = B()
+        else:
+            x = C()
+        return x.f()
+    res = interpret(f, [True])
+    assert res == 2
+    res = interpret(f, [False])
+    assert res == 3



More information about the Pypy-commit mailing list