Author: Matti Picus <matti.pi...@gmail.com>
Branch: cpyext-datetime2
Changeset: r93680:862b4b1c5eda
Date: 2018-01-18 20:04 +0200
http://bitbucket.org/pypy/pypy/changeset/862b4b1c5eda/

Log:    make headers compatible with cpython, prevent recursive tp_dealloc

diff --git a/pypy/module/cpyext/cdatetime.py b/pypy/module/cpyext/cdatetime.py
--- a/pypy/module/cpyext/cdatetime.py
+++ b/pypy/module/cpyext/cdatetime.py
@@ -1,5 +1,6 @@
 from rpython.rtyper.lltypesystem import rffi, lltype
 from rpython.rtyper.annlowlevel import llhelper
+from rpython.rlib.rarithmetic import widen
 from pypy.module.cpyext.pyobject import (PyObject, make_ref, make_typedescr,
     decref)
 from pypy.module.cpyext.api import (cpython_api, CANNOT_FAIL, cpython_struct,
@@ -16,8 +17,12 @@
 
 PyDateTime_CAPI = cts.gettype('PyDateTime_CAPI')
 
+datetimeAPI_global = []
+
 @cpython_api([], lltype.Ptr(PyDateTime_CAPI))
 def _PyDateTime_Import(space):
+    if len(datetimeAPI_global) >0:
+        return datetimeAPI_global[0]
     datetimeAPI = lltype.malloc(PyDateTime_CAPI, flavor='raw',
                                 track_allocation=False)
 
@@ -56,9 +61,11 @@
         _PyDelta_FromDelta.api_func.functype,
         _PyDelta_FromDelta.api_func.get_wrapper(space))
 
+    datetimeAPI_global.append(datetimeAPI)
     return datetimeAPI
 
 PyDateTime_Time = cts.gettype('PyDateTime_Time*')
+PyDateTime_DateTime = cts.gettype('PyDateTime_DateTime*')
 PyDateTime_Date = cts.gettype('PyDateTime_Date*')
 PyDateTime_Delta = cts.gettype('PyDateTime_Delta*')
 
@@ -110,6 +117,22 @@
                    dealloc=type_dealloc,
                   )
 
+    # why do we need date_dealloc? Since W_DateTime_Date is the base class for
+    # app level datetime.date. If a c-extension class uses datetime.date for 
its
+    # base class and defines a tp_dealloc, we will get this:
+    # c_class->tp_dealloc == tp_dealloc_func
+    # c_class->tp_base == datetime.date, 
+    #                     datetime.date->tp_dealloc = _PyPy_subtype_dealloc
+    # datetime.date->tp_base = W_DateTime_Date
+    #                    W_DateTime_Date->tp_dealloc = _PyPy_subtype_dealloc
+    # but _PyPy_subtype_dealloc will call tp_dealloc_func, which can call its
+    # base's tp_dealloc and we get recursion. So break the recursion by setting
+    # W_DateTime_Date->tp_dealloc
+    make_typedescr(W_DateTime_Date.typedef,
+                   basestruct=PyDateTime_DateTime.TO,
+                   dealloc=date_dealloc,
+                  )
+
     make_typedescr(W_DateTime_Delta.typedef,
                    basestruct=PyDateTime_Delta.TO,
                    attach=timedeltatype_attach,
@@ -122,29 +145,34 @@
     py_datetime = rffi.cast(PyDateTime_Time, py_obj)
     w_tzinfo = space.getattr(w_obj, space.newtext('tzinfo'))
     if space.is_none(w_tzinfo):
-        py_datetime.c_hastzinfo = 0
+        py_datetime.c_hastzinfo = cts.cast('unsigned char', 0)
         py_datetime.c_tzinfo = lltype.nullptr(PyObject.TO)
     else:
-        py_datetime.c_hastzinfo = 1
+        py_datetime.c_hastzinfo = cts.cast('unsigned char', 1)
         py_datetime.c_tzinfo = make_ref(space, w_tzinfo)
 
 @slot_function([PyObject], lltype.Void)
 def type_dealloc(space, py_obj):
     py_datetime = rffi.cast(PyDateTime_Time, py_obj)
-    if (py_datetime.c_hastzinfo != 0):
+    if (widen(py_datetime.c_hastzinfo) != 0):
         decref(space, py_datetime.c_tzinfo)
     from pypy.module.cpyext.object import _dealloc
     _dealloc(space, py_obj)
 
+@slot_function([PyObject], lltype.Void)
+def date_dealloc(space, py_obj):
+    from pypy.module.cpyext.object import _dealloc
+    _dealloc(space, py_obj)
+
 def timedeltatype_attach(space, py_obj, w_obj, w_userdata=None):
     "Fills a newly allocated py_obj from the w_obj"
     py_delta = rffi.cast(PyDateTime_Delta, py_obj)
     days = space.int_w(space.getattr(w_obj, space.newtext('days')))
-    py_delta.c_days = days
+    py_delta.c_days = cts.cast('int', days)
     seconds = space.int_w(space.getattr(w_obj, space.newtext('seconds')))
-    py_delta.c_seconds = seconds
+    py_delta.c_seconds = cts.cast('int', seconds)
     microseconds = space.int_w(space.getattr(w_obj, 
space.newtext('microseconds')))
-    py_delta.c_microseconds = microseconds
+    py_delta.c_microseconds = cts.cast('int', microseconds)
 
 # Constructors. They are better used as macros.
 
diff --git a/pypy/module/cpyext/include/datetime.h 
b/pypy/module/cpyext/include/datetime.h
--- a/pypy/module/cpyext/include/datetime.h
+++ b/pypy/module/cpyext/include/datetime.h
@@ -5,12 +5,10 @@
 #endif
 
 #include "cpyext_datetime.h"
+
 PyAPI_DATA(PyDateTime_CAPI*) PyDateTimeAPI;
-#define PyDateTime_IMPORT                           \
-    do {                                            \
-        if(PyDateTimeAPI==NULL)                     \
-            PyDateTimeAPI = _PyDateTime_Import();   \
-    } while (0)
+
+#define PyDateTime_IMPORT (PyDateTimeAPI = _PyDateTime_Import())
 
 /* Macros for accessing constructors in a simplified fashion. */
 #define PyDate_FromDate(year, month, day) \
diff --git a/pypy/module/cpyext/parse/cpyext_datetime.h 
b/pypy/module/cpyext/parse/cpyext_datetime.h
--- a/pypy/module/cpyext/parse/cpyext_datetime.h
+++ b/pypy/module/cpyext/parse/cpyext_datetime.h
@@ -18,9 +18,9 @@
 typedef struct
 {
     PyObject_HEAD
-    long days;                   /* -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS 
*/
-    long seconds;                /* 0 <= seconds < 24*3600 is invariant */
-    long microseconds;           /* 0 <= microseconds < 1000000 is invariant */
+    int days;                   /* -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS */
+    int seconds;                /* 0 <= seconds < 24*3600 is invariant */
+    int microseconds;           /* 0 <= microseconds < 1000000 is invariant */
 } PyDateTime_Delta;
 
 /* The datetime and time types have an optional tzinfo member,
@@ -29,14 +29,14 @@
 typedef struct
 {
     PyObject_HEAD
-    long hastzinfo;
+    unsigned char hastzinfo;
     PyObject *tzinfo;
 } PyDateTime_Time;
 
 typedef struct
 {
     PyObject_HEAD
-    long hastzinfo;
+    unsigned char hastzinfo;
     PyObject *tzinfo;
 } PyDateTime_DateTime;
 
@@ -45,3 +45,8 @@
     PyObject_HEAD
 } PyDateTime_Date;
 
+
+typedef struct {
+    PyObject_HEAD
+} PyDateTime_TZInfo;
+
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to