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