[pypy-svn] r75192 - in pypy/trunk/pypy/module/cpyext: . include test

afa at codespeak.net afa at codespeak.net
Tue Jun 8 14:58:56 CEST 2010


Author: afa
Date: Tue Jun  8 14:58:54 2010
New Revision: 75192

Modified:
   pypy/trunk/pypy/module/cpyext/api.py
   pypy/trunk/pypy/module/cpyext/datetime.py
   pypy/trunk/pypy/module/cpyext/include/datetime.h
   pypy/trunk/pypy/module/cpyext/test/test_datetime.py
Log:
Add the PyDateTime_CAPI structure, that holds common types from the datetime module.

2 caveats:
- the datetime module is now pre-loaded in pypy-c
- api.py really needs some refactoring.


Modified: pypy/trunk/pypy/module/cpyext/api.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/api.py	(original)
+++ pypy/trunk/pypy/module/cpyext/api.py	Tue Jun  8 14:58:54 2010
@@ -315,6 +315,7 @@
     '_Py_TrueStruct#': ('PyObject*', 'space.w_True'),
     '_Py_ZeroStruct#': ('PyObject*', 'space.w_False'),
     '_Py_NotImplementedStruct#': ('PyObject*', 'space.w_NotImplemented'),
+    'PyDateTimeAPI': ('PyDateTime_CAPI*', 'cpyext.datetime.build_datetime_api(space)'),
     }
 FORWARD_DECLS = []
 INIT_FUNCTIONS = []
@@ -360,7 +361,9 @@
 
 def get_structtype_for_ctype(ctype):
     from pypy.module.cpyext.typeobjectdefs import PyTypeObjectPtr
-    return {"PyObject*": PyObject, "PyTypeObject*": PyTypeObjectPtr}[ctype]
+    from pypy.module.cpyext.datetime import PyDateTime_CAPI
+    return {"PyObject*": PyObject, "PyTypeObject*": PyTypeObjectPtr,
+            "PyDateTime_CAPI*": lltype.Ptr(PyDateTime_CAPI)}[ctype]
 
 PyTypeObject = lltype.ForwardReference()
 PyTypeObjectPtr = lltype.Ptr(PyTypeObject)
@@ -506,13 +509,14 @@
                                       % (callable.__name__,))
                 retval = error_value
 
-            elif callable.api_func.restype is PyObject:
+            elif is_PyObject(callable.api_func.restype):
                 if result is None:
                     retval = make_ref(space, None)
                 elif isinstance(result, BorrowPair):
                     retval = result.get_ref(space)
                 elif not rffi._isllptr(result):
-                    retval = make_ref(space, result)
+                    retval = rffi.cast(callable.api_func.restype,
+                                       make_ref(space, result))
                 else:
                     retval = result
             elif callable.api_func.restype is not lltype.Void:
@@ -612,8 +616,10 @@
     for name, (typ, expr) in GLOBALS.iteritems():
         if "#" in name:
             continue
-        if name.startswith('PyExc_'):
-            global_objects.append('%s %s;' % (typ[:-1], '_' + name))
+        if typ == 'PyDateTime_CAPI*':
+            global_objects.append('%s _%s;' % (typ, name))
+        elif name.startswith('PyExc_'):
+            global_objects.append('%s _%s;' % (typ[:-1], name))
         else:
             global_objects.append('%s %s = NULL;' % (typ, name))
     global_code = '\n'.join(global_objects)
@@ -653,7 +659,13 @@
         name = name.replace('Py', 'PyPy')
         if isptr:
             ptr = ctypes.c_void_p.in_dll(bridge, name)
-            ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(make_ref(space, w_obj)),
+            if typ == 'PyObject*':
+                value = make_ref(space, w_obj)
+            elif typ == 'PyDateTime_CAPI*':
+                value = w_obj
+            else:
+                assert False, "Unknown static pointer: %s %s" % (typ, name)
+            ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(value),
                                     ctypes.c_void_p).value
         elif typ in ('PyObject*', 'PyTypeObject*'):
             if name.startswith('PyPyExc_'):
@@ -804,6 +816,9 @@
         elif name.startswith('PyExc_'):
             structs.append('extern PyTypeObject _%s;' % (name,))
             structs.append('PyObject* %s = (PyObject*)&_%s;' % (name, name))
+        elif typ == 'PyDateTime_CAPI*':
+            structs.append('extern %s _%s;' % (typ[:-1], name))
+            structs.append('%s %s = &_%s;' % (typ, name, name))
     struct_file.write('\n'.join(structs))
 
     eci = ExternalCompilationInfo(
@@ -853,7 +868,13 @@
             name = '_' + name
         from pypy.module import cpyext
         w_obj = eval(expr)
-        struct_ptr = make_ref(space, w_obj)
+        if typ in ('PyObject*', 'PyTypeObject*'):
+            struct_ptr = make_ref(space, w_obj)
+        elif typ == 'PyDateTime_CAPI*':
+            struct_ptr = w_obj
+            name = '_' + name
+        else:
+            assert False, "Unknown static data: %s %s" % (typ, name)
         struct = rffi.cast(get_structtype_for_ctype(typ), struct_ptr)._obj
         struct._compilation_info = eci
         export_struct(name, struct)
@@ -946,7 +967,7 @@
         assert len(args) == len(FT.ARGS)
         for i, ARG in unrolling_arg_types:
             arg = args[i]
-            if ARG is PyObject:
+            if is_PyObject(ARG):
                 if arg is None:
                     boxed_args += (lltype.nullptr(PyObject.TO),)
                 elif isinstance(arg, W_Root):
@@ -969,7 +990,7 @@
             finally:
                 state.swap_borrow_container(old_container)
 
-            if RESULT_TYPE is PyObject:
+            if is_PyObject(RESULT_TYPE):
                 if result is None:
                     ret = result
                 elif isinstance(result, W_Root):

Modified: pypy/trunk/pypy/module/cpyext/datetime.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/datetime.py	(original)
+++ pypy/trunk/pypy/module/cpyext/datetime.py	Tue Jun  8 14:58:54 2010
@@ -1,14 +1,42 @@
 from pypy.rpython.lltypesystem import rffi, lltype
-from pypy.module.cpyext.pyobject import PyObject
+from pypy.module.cpyext.pyobject import PyObject, make_ref
 from pypy.module.cpyext.api import (
     cpython_api, CANNOT_FAIL, cpython_struct, PyObjectFields)
 from pypy.module.cpyext.import_ import PyImport_Import
+from pypy.module.cpyext.typeobject import PyTypeObjectPtr
 from pypy.interpreter.error import OperationError
 from pypy.tool.sourcetools import func_renamer
 
 # API import function
 
- at cpython_api([], lltype.Void)
+PyDateTime_CAPI = cpython_struct(
+    'PyDateTime_CAPI',
+    (('DateType', PyTypeObjectPtr),
+     ('DateTimeType', PyTypeObjectPtr),
+     ('TimeType', PyTypeObjectPtr),
+     ('DeltaType', PyTypeObjectPtr),
+     ))
+
+def build_datetime_api(space):
+    w_datetime = PyImport_Import(space, space.wrap("datetime"))
+    datetimeAPI = lltype.malloc(PyDateTime_CAPI, flavor='raw')
+
+    w_type = space.getattr(w_datetime, space.wrap("date"))
+    datetimeAPI.c_DateType = rffi.cast(
+        PyTypeObjectPtr, make_ref(space, w_type))
+    w_type = space.getattr(w_datetime, space.wrap("datetime"))
+    datetimeAPI.c_DateTimeType = rffi.cast(
+        PyTypeObjectPtr, make_ref(space, w_type))
+    w_type = space.getattr(w_datetime, space.wrap("time"))
+    datetimeAPI.c_TimeType = rffi.cast(
+        PyTypeObjectPtr, make_ref(space, w_type))
+    w_type = space.getattr(w_datetime, space.wrap("timedelta"))
+    datetimeAPI.c_DeltaType = rffi.cast(
+        PyTypeObjectPtr, make_ref(space, w_type))
+
+    return datetimeAPI
+
+ at cpython_api([], PyObject)
 def _PyDateTime_Import(space):
     return
 

Modified: pypy/trunk/pypy/module/cpyext/include/datetime.h
==============================================================================
--- pypy/trunk/pypy/module/cpyext/include/datetime.h	(original)
+++ pypy/trunk/pypy/module/cpyext/include/datetime.h	Tue Jun  8 14:58:54 2010
@@ -4,6 +4,16 @@
 extern "C" {
 #endif
 
+/* Define structure for C API. */
+typedef struct {
+    /* type objects */
+    PyTypeObject *DateType;
+    PyTypeObject *DateTimeType;
+    PyTypeObject *TimeType;
+    PyTypeObject *DeltaType;
+} PyDateTime_CAPI;
+
+PyAPI_DATA(PyDateTime_CAPI*) PyDateTimeAPI;
 #define PyDateTime_IMPORT _PyDateTime_Import()
 
 typedef struct {

Modified: pypy/trunk/pypy/module/cpyext/test/test_datetime.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/test/test_datetime.py	(original)
+++ pypy/trunk/pypy/module/cpyext/test/test_datetime.py	Tue Jun  8 14:58:54 2010
@@ -79,3 +79,21 @@
         w_date = api.PyDateTime_FromTimestamp(w_args)
         date = datetime.datetime.fromtimestamp(0)
         assert space.unwrap(space.str(w_date)) == str(date)
+
+class AppTestDatetime(AppTestCpythonExtensionBase):
+    def test_CAPI(self):
+        module = self.import_extension('foo', [
+            ("get_types", "METH_NOARGS",
+             """
+                 return PyTuple_Pack(4,
+                                     PyDateTimeAPI->DateType,
+                                     PyDateTimeAPI->DateTimeType,
+                                     PyDateTimeAPI->TimeType,
+                                     PyDateTimeAPI->DeltaType);
+             """),
+            ])
+        import datetime
+        assert module.get_types() == (datetime.date,
+                                      datetime.datetime,
+                                      datetime.time,
+                                      datetime.timedelta)



More information about the Pypy-commit mailing list