diff options
author | Paul Ganssle <pganssle@users.noreply.github.com> | 2019-04-27 19:39:40 (GMT) |
---|---|---|
committer | Berker Peksag <berker.peksag@gmail.com> | 2019-04-27 19:39:40 (GMT) |
commit | 4d8c8c0ad6163c24136d3419eb04f310b31f7e64 (patch) | |
tree | 445d3de23677da75d5c1d3346a45d799b4874b48 /Modules/_testcapimodule.c | |
parent | 5c403b203510549a3f89d138d3265c5cc0cc12af (diff) | |
download | cpython-4d8c8c0ad6163c24136d3419eb04f310b31f7e64.zip cpython-4d8c8c0ad6163c24136d3419eb04f310b31f7e64.tar.gz cpython-4d8c8c0ad6163c24136d3419eb04f310b31f7e64.tar.bz2 |
bpo-36025: Fix PyDate_FromTimestamp API (GH-11922)
In the process of converting the date.fromtimestamp function to use
argument clinic in GH-8535, the C API for PyDate_FromTimestamp was
inadvertently changed to expect a timestamp object rather than an
argument tuple.
This PR fixes this backwards-incompatible change by adding a new wrapper
function for the C API function that unwraps the argument tuple and
passes it to the underlying function.
This PR also adds tests for both PyDate_FromTimestamp and
PyDateTime_FromTimestamp to prevent any further regressions.
Diffstat (limited to 'Modules/_testcapimodule.c')
-rw-r--r-- | Modules/_testcapimodule.c | 69 |
1 files changed, 68 insertions, 1 deletions
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 6f4eb53..c52e349 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -2340,6 +2340,71 @@ get_timezone_utc_capi(PyObject* self, PyObject *args) { } } +static PyObject * +get_date_fromtimestamp(PyObject* self, PyObject *args) +{ + PyObject *tsargs = NULL, *ts = NULL, *rv = NULL; + int macro = 0; + + if (!PyArg_ParseTuple(args, "O|p", &ts, ¯o)) { + return NULL; + } + + // Construct the argument tuple + if ((tsargs = PyTuple_Pack(1, ts)) == NULL) { + return NULL; + } + + // Pass along to the API function + if (macro) { + rv = PyDate_FromTimestamp(tsargs); + } + else { + rv = PyDateTimeAPI->Date_FromTimestamp( + (PyObject *)PyDateTimeAPI->DateType, tsargs + ); + } + + Py_DECREF(tsargs); + return rv; +} + +static PyObject * +get_datetime_fromtimestamp(PyObject* self, PyObject *args) +{ + int macro = 0; + int usetz = 0; + PyObject *tsargs = NULL, *ts = NULL, *tzinfo = Py_None, *rv = NULL; + if (!PyArg_ParseTuple(args, "OO|pp", &ts, &tzinfo, &usetz, ¯o)) { + return NULL; + } + + // Construct the argument tuple + if (usetz) { + tsargs = PyTuple_Pack(2, ts, tzinfo); + } + else { + tsargs = PyTuple_Pack(1, ts); + } + + if (tsargs == NULL) { + return NULL; + } + + // Pass along to the API function + if (macro) { + rv = PyDateTime_FromTimestamp(tsargs); + } + else { + rv = PyDateTimeAPI->DateTime_FromTimestamp( + (PyObject *)PyDateTimeAPI->DateTimeType, tsargs, NULL + ); + } + + Py_DECREF(tsargs); + return rv; +} + /* test_thread_state spawns a thread of its own, and that thread releases * `thread_done` when it's finished. The driver code has to know when the @@ -4769,7 +4834,9 @@ static PyMethodDef TestMethods[] = { {"datetime_check_tzinfo", datetime_check_tzinfo, METH_VARARGS}, {"make_timezones_capi", make_timezones_capi, METH_NOARGS}, {"get_timezones_offset_zero", get_timezones_offset_zero, METH_NOARGS}, - {"get_timezone_utc_capi", get_timezone_utc_capi, METH_VARARGS}, + {"get_timezone_utc_capi", get_timezone_utc_capi, METH_VARARGS}, + {"get_date_fromtimestamp", get_date_fromtimestamp, METH_VARARGS}, + {"get_datetime_fromtimestamp", get_datetime_fromtimestamp, METH_VARARGS}, {"test_list_api", test_list_api, METH_NOARGS}, {"test_dict_iteration", test_dict_iteration, METH_NOARGS}, {"dict_getitem_knownhash", dict_getitem_knownhash, METH_VARARGS}, |