[pypy-commit] pypy missing-tp_new: Starting to support this: fill the slots of a PyTypeObject corresponding

arigo pypy.commits at gmail.com
Sun Oct 30 12:26:38 EDT 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: missing-tp_new
Changeset: r87995:ae922c5e17f2
Date: 2016-10-30 17:26 +0100
http://bitbucket.org/pypy/pypy/changeset/ae922c5e17f2/

Log:	Starting to support this: fill the slots of a PyTypeObject
	corresponding to an app-level class which defines some '__xxx__'
	special methods

diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -17,6 +17,7 @@
 from pypy.module.cpyext.pyerrors import PyErr_Occurred
 from pypy.module.cpyext.memoryobject import fill_Py_buffer
 from pypy.module.cpyext.state import State
+from pypy.module.cpyext import userslot
 from pypy.interpreter.error import OperationError, oefmt
 from pypy.interpreter.argument import Arguments
 from rpython.rlib.buffer import Buffer
@@ -430,6 +431,10 @@
 
 @specialize.memo()
 def get_slot_tp_function(space, typedef, name):
+    """Return a description of the slot C function to use for the built-in
+    type for 'typedef'.  The 'name' is the slot name.  This is a memo
+    function that, after translation, returns one of a built-in finite set.
+    """
     key = (typedef, name)
     try:
         return SLOTS[key]
@@ -680,7 +685,7 @@
         else:
             assert False
 
-    function = globals().get(FUNCTION, None)
+    function = getattr(userslot, FUNCTION or '!missing', None)
     assert FLAGS == 0 or FLAGS == PyWrapperFlag_KEYWORDS
     if FLAGS:
         if wrapper is Ellipsis:
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -1,7 +1,7 @@
 import os
 
 from rpython.rlib import jit
-from rpython.rlib.objectmodel import specialize
+from rpython.rlib.objectmodel import specialize, we_are_translated
 from rpython.rlib.rstring import rsplit
 from rpython.rtyper.annlowlevel import llhelper
 from rpython.rtyper.lltypesystem import rffi, lltype
@@ -37,8 +37,6 @@
 from pypy.objspace.std.typeobject import W_TypeObject, find_best_base
 
 
-WARN_ABOUT_MISSING_SLOT_FUNCTIONS = False
-
 PyType_Check, PyType_CheckExact = build_type_checkers("Type", "w_type")
 
 PyHeapTypeObjectStruct = lltype.ForwardReference()
@@ -246,33 +244,32 @@
     # overwrite slots that are already set: these ones are probably
     # coming from a parent C type.
 
-    typedef = w_type.layout.typedef
+    if w_type.is_heaptype():
+        typedef = None
+    else:
+        typedef = w_type.layout.typedef
+
     for method_name, slot_name, slot_names, slot_func in slotdefs_for_tp_slots:
         w_descr = w_type.lookup(method_name)
         if w_descr is None:
             # XXX special case iternext
             continue
 
-        slot_func_helper = None
+        if slot_func is None:
+            slot_func_helper = None
+        else:
+            slot_func_helper = llhelper(slot_func.api_func.functype,
+                                        slot_func.api_func.get_wrapper(space))
 
-        if slot_func is None and typedef is not None:
-            # XXX note that the w_type is retrieved inside this call via
-            # w_type = space.gettypeobject(typedef)
-            if w_type.name == 'Date' and slot_name == 'tp_new':
-                name = space.gettypeobject(typedef).name
-                print 'w_type inside build_slot_tp_function is "%s", wanted "%s"' %(
-                        name, w_type.name)
+        if typedef is not None:
             get_slot = get_slot_tp_function(space, typedef, slot_name)
             if get_slot:
                 slot_func_helper = get_slot()
-        elif slot_func:
-            slot_func_helper = llhelper(slot_func.api_func.functype,
-                                        slot_func.api_func.get_wrapper(space))
 
         if slot_func_helper is None:
-            if WARN_ABOUT_MISSING_SLOT_FUNCTIONS:
-                os.write(2, "%s defined by %s but no slot function defined!\n" % (
-                        method_name, w_type.getname(space)))
+            if not we_are_translated():
+                print "missing slot %r/%r for %r" % (
+                    method_name, slot_name, w_type.getname(space))
             continue
 
         # XXX special case wrapper-functions and use a "specific" slot func
diff --git a/pypy/module/cpyext/userslot.py b/pypy/module/cpyext/userslot.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/userslot.py
@@ -0,0 +1,26 @@
+"""
+These are the default implementation for type slots that we put
+in user-defined app-level Python classes, if the class implements
+the corresponding '__xxx__' special method.  It should mostly just
+call back the general version of the space operation.
+
+This is only approximately correct.  One problem is that some
+details are likely subtly wrong.  Another problem is that we don't
+track changes to an app-level Python class (addition or removal of
+'__xxx__' special methods) after initalization of the PyTypeObject.
+"""
+
+from pypy.module.cpyext.api import cpython_api, PyObject, Py_ssize_t
+
+
+ at cpython_api([PyObject], Py_ssize_t, error=-1, header=None)
+def slot_sq_length(space, w_obj):
+    return space.int_w(space.len(w_obj))
+
+ at cpython_api([PyObject, Py_ssize_t], PyObject, header=None)
+def slot_sq_item(space, w_obj, index):
+    return space.getitem(w_obj, space.wrap(index))
+
+ at cpython_api([PyObject, PyObject], PyObject, header=None)
+def slot_nb_add(space, w_obj1, w_obj2):
+    return space.add(w_obj1, w_obj2)


More information about the pypy-commit mailing list