Author: Matti Picus <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit