[pypy-commit] pypy datetime_api_27: Add _FromTimestamp methods to CAPI capsule
pganssle
pypy.commits at gmail.com
Sun Apr 14 10:00:15 EDT 2019
Author: Paul Ganssle <paul at ganssle.io>
Branch: datetime_api_27
Changeset: r96483:d5b44bb7b84d
Date: 2019-04-12 12:44 -0400
http://bitbucket.org/pypy/pypy/changeset/d5b44bb7b84d/
Log: Add _FromTimestamp methods to CAPI capsule
The CPython CAPI capsule includes fromtimestamp constructors, but
the current cpyext implementation does not, which causes some
problems for people writing C extensions that use the capsule
directly rather than the C macros.
Closes bitbucket issue #2986:
https://bitbucket.org/pypy/pypy/issues/2986
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
@@ -67,6 +67,14 @@
_PyDelta_FromDelta.api_func.functype,
_PyDelta_FromDelta.api_func.get_wrapper(space))
+ datetimeAPI.c_DateTime_FromTimestamp = llhelper(
+ _PyDateTime_FromTimestamp.api_func.functype,
+ _PyDateTime_FromTimestamp.api_func.get_wrapper(space))
+
+ datetimeAPI.c_Date_FromTimestamp = llhelper(
+ _PyDate_FromTimestamp.api_func.functype,
+ _PyDate_FromTimestamp.api_func.get_wrapper(space))
+
state.datetimeAPI.append(datetimeAPI)
return state.datetimeAPI[0]
@@ -243,8 +251,16 @@
"""
w_datetime = PyImport_Import(space, space.newtext("datetime"))
w_type = space.getattr(w_datetime, space.newtext("datetime"))
+ return _PyDateTime_FromTimestamp(space, w_type, w_args, None)
+
+ at cpython_api([PyObject, PyObject, PyObject], PyObject)
+def _PyDateTime_FromTimestamp(space, w_type, w_args, w_kwds):
+ """Implementation of datetime.fromtimestamp that matches the signature for
+ PyDatetimeCAPI.DateTime_FromTimestamp
+ """
w_method = space.getattr(w_type, space.newtext("fromtimestamp"))
- return space.call(w_method, w_args)
+
+ return space.call(w_method, w_args, w_kwds=w_kwds)
@cpython_api([PyObject], PyObject)
def PyDate_FromTimestamp(space, w_args):
@@ -253,6 +269,12 @@
"""
w_datetime = PyImport_Import(space, space.newtext("datetime"))
w_type = space.getattr(w_datetime, space.newtext("date"))
+ return _PyDate_FromTimestamp(space, w_type, w_args)
+
+ at cpython_api([PyObject, PyObject], PyObject)
+def _PyDate_FromTimestamp(space, w_type, w_args):
+ """Implementation of date.fromtimestamp that matches the signature for
+ PyDatetimeCAPI.Date_FromTimestamp"""
w_method = space.getattr(w_type, space.newtext("fromtimestamp"))
return space.call(w_method, w_args)
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
@@ -13,6 +13,10 @@
PyObject*, PyTypeObject*);
PyObject *(*Time_FromTime)(int, int, int, int, PyObject*, PyTypeObject*);
PyObject *(*Delta_FromDelta)(int, int, int, int, PyTypeObject*);
+
+ /* constructors for the DB API */
+ PyObject *(*DateTime_FromTimestamp)(PyObject*, PyObject*, PyObject*);
+ PyObject *(*Date_FromTimestamp)(PyObject*, PyObject*);
} PyDateTime_CAPI;
typedef struct
diff --git a/pypy/module/cpyext/test/test_datetime.py b/pypy/module/cpyext/test/test_datetime.py
--- a/pypy/module/cpyext/test/test_datetime.py
+++ b/pypy/module/cpyext/test/test_datetime.py
@@ -146,6 +146,41 @@
2000, 6, 6, 6, 6, 6, 6, Py_None,
PyDateTimeAPI->DateTimeType);
"""),
+ ("new_datetime_fromtimestamp", "METH_NOARGS",
+ """ PyDateTime_IMPORT;
+ PyObject *ts = PyFloat_FromDouble(200000.0);
+ Py_INCREF(Py_None);
+ PyObject *tsargs = PyTuple_Pack(2, ts, Py_None);
+ PyObject *rv = PyDateTimeAPI->DateTime_FromTimestamp(
+ (PyObject *)PyDateTimeAPI->DateTimeType, tsargs, NULL);
+ Py_DECREF(tsargs);
+ return rv;
+ """),
+ ("new_dt_fromts_tzinfo", "METH_O",
+ """ PyDateTime_IMPORT;
+ PyObject *ts = PyFloat_FromDouble(200000.0);
+ PyObject *tsargs = PyTuple_Pack(1, ts);
+ PyObject *tskwargs = PyDict_New();
+
+ Py_INCREF(args);
+ PyDict_SetItemString(tskwargs, "tz", args);
+ PyObject *rv = PyDateTimeAPI->DateTime_FromTimestamp(
+ (PyObject *)PyDateTimeAPI->DateTimeType, tsargs, tskwargs);
+ Py_DECREF(tsargs);
+ Py_DECREF(tskwargs);
+ return rv;
+ """),
+ ("new_date_fromtimestamp", "METH_NOARGS",
+ """ PyDateTime_IMPORT;
+ PyObject *ts = PyFloat_FromDouble(1430366400.0);
+ Py_INCREF(Py_None);
+ PyObject *tsargs = PyTuple_Pack(1, ts);
+ PyObject *rv = PyDateTimeAPI->Date_FromTimestamp(
+ (PyObject *)PyDateTimeAPI->DateType, tsargs);
+ Py_DECREF(tsargs);
+ return rv;
+ """),
+
], prologue='#include "datetime.h"\n')
import datetime
assert module.new_date() == datetime.date(2000, 6, 6)
@@ -153,6 +188,28 @@
assert module.new_datetime() == datetime.datetime(
2000, 6, 6, 6, 6, 6, 6)
+ class UTC(datetime.tzinfo):
+ def utcoffset(self, dt):
+ return datetime.timedelta(hours=0)
+
+ def dst(self, dt):
+ return datetime.timedelta(0)
+
+ def tzname(self, dt):
+ return "UTC"
+
+ utc = UTC()
+
+ # .fromtimestamp tests
+ assert (module.new_datetime_fromtimestamp() ==
+ datetime.datetime.fromtimestamp(200000.0))
+
+ assert (module.new_dt_fromts_tzinfo(utc) ==
+ datetime.datetime.fromtimestamp(200000.0, tz=utc))
+
+ assert (module.new_date_fromtimestamp() ==
+ datetime.date.fromtimestamp(1430366400.0))
+
def test_macros(self):
module = self.import_extension('foo', [
("test_date_macros", "METH_NOARGS",
@@ -305,16 +362,18 @@
"""),
], prologue='#include "datetime.h"\n')
from datetime import tzinfo, datetime, timedelta, time
+
# copied from datetime documentation
class GMT1(tzinfo):
def __del__(self):
- print 'deleting GMT1'
+ print('deleting GMT1')
def utcoffset(self, dt):
return timedelta(hours=1) + self.dst(dt)
def dst(self, dt):
return timedelta(0)
def tzname(self,dt):
return "GMT +1"
+
gmt1 = GMT1()
dt1 = module.time_with_tzinfo(gmt1)
assert dt1 == time(6, 6, 6, 6, gmt1)
More information about the pypy-commit
mailing list