]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-93649: Split pytime and datetime tests from _testcapimodule.c (#99494)
authorErlend E. Aasland <erlend.aasland@protonmail.com>
Tue, 15 Nov 2022 07:17:52 +0000 (08:17 +0100)
committerGitHub <noreply@github.com>
Tue, 15 Nov 2022 07:17:52 +0000 (08:17 +0100)
Modules/Setup.stdlib.in
Modules/_testcapi/datetime.c [new file with mode: 0644]
Modules/_testcapi/parts.h
Modules/_testcapi/pytime.c [new file with mode: 0644]
Modules/_testcapimodule.c
PCbuild/_testcapi.vcxproj
PCbuild/_testcapi.vcxproj.filters

index b672ea908eec11062441f14942510f57b371a443..e250f83c5a4a65ea97712a6087ea15a3aed318ea 100644 (file)
 @MODULE__XXTESTFUZZ_TRUE@_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c
 @MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c
 @MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c
-@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/vectorcall_limited.c _testcapi/heaptype.c _testcapi/unicode.c _testcapi/getargs.c
+@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/vectorcall_limited.c _testcapi/heaptype.c _testcapi/unicode.c _testcapi/getargs.c _testcapi/pytime.c _testcapi/datetime.c
 
 # Some testing modules MUST be built as shared libraries.
 *shared*
diff --git a/Modules/_testcapi/datetime.c b/Modules/_testcapi/datetime.c
new file mode 100644 (file)
index 0000000..9fb6562
--- /dev/null
@@ -0,0 +1,453 @@
+#include "parts.h"
+
+#include "datetime.h"             // PyDateTimeAPI
+
+
+static int test_run_counter = 0;
+
+static PyObject *
+test_datetime_capi(PyObject *self, PyObject *args)
+{
+    if (PyDateTimeAPI) {
+        if (test_run_counter) {
+            /* Probably regrtest.py -R */
+            Py_RETURN_NONE;
+        }
+        else {
+            PyErr_SetString(PyExc_AssertionError,
+                            "PyDateTime_CAPI somehow initialized");
+            return NULL;
+        }
+    }
+    test_run_counter++;
+    PyDateTime_IMPORT;
+
+    if (PyDateTimeAPI) {
+        Py_RETURN_NONE;
+    }
+    return NULL;
+}
+
+/* Functions exposing the C API type checking for testing */
+#define MAKE_DATETIME_CHECK_FUNC(check_method, exact_method)    \
+do {                                                            \
+    PyObject *obj;                                              \
+    int exact = 0;                                              \
+    if (!PyArg_ParseTuple(args, "O|p", &obj, &exact)) {         \
+        return NULL;                                            \
+    }                                                           \
+    int rv = exact?exact_method(obj):check_method(obj);         \
+    if (rv) {                                                   \
+        Py_RETURN_TRUE;                                         \
+    }                                                           \
+    Py_RETURN_FALSE;                                            \
+} while (0)                                                     \
+
+static PyObject *
+datetime_check_date(PyObject *self, PyObject *args)
+{
+    MAKE_DATETIME_CHECK_FUNC(PyDate_Check, PyDate_CheckExact);
+}
+
+static PyObject *
+datetime_check_time(PyObject *self, PyObject *args)
+{
+    MAKE_DATETIME_CHECK_FUNC(PyTime_Check, PyTime_CheckExact);
+}
+
+static PyObject *
+datetime_check_datetime(PyObject *self, PyObject *args)
+{
+    MAKE_DATETIME_CHECK_FUNC(PyDateTime_Check, PyDateTime_CheckExact);
+}
+
+static PyObject *
+datetime_check_delta(PyObject *self, PyObject *args)
+{
+    MAKE_DATETIME_CHECK_FUNC(PyDelta_Check, PyDelta_CheckExact);
+}
+
+static PyObject *
+datetime_check_tzinfo(PyObject *self, PyObject *args)
+{
+    MAKE_DATETIME_CHECK_FUNC(PyTZInfo_Check, PyTZInfo_CheckExact);
+}
+#undef MAKE_DATETIME_CHECK_FUNC
+
+
+/* Makes three variations on timezone representing UTC-5:
+   1. timezone with offset and name from PyDateTimeAPI
+   2. timezone with offset and name from PyTimeZone_FromOffsetAndName
+   3. timezone with offset (no name) from PyTimeZone_FromOffset
+*/
+static PyObject *
+make_timezones_capi(PyObject *self, PyObject *args)
+{
+    PyObject *offset = PyDelta_FromDSU(0, -18000, 0);
+    PyObject *name = PyUnicode_FromString("EST");
+
+    PyObject *est_zone_capi = PyDateTimeAPI->TimeZone_FromTimeZone(offset, name);
+    PyObject *est_zone_macro = PyTimeZone_FromOffsetAndName(offset, name);
+    PyObject *est_zone_macro_noname = PyTimeZone_FromOffset(offset);
+
+    Py_DecRef(offset);
+    Py_DecRef(name);
+
+    PyObject *rv = PyTuple_New(3);
+    if (rv == NULL) {
+        return NULL;
+    }
+
+    PyTuple_SET_ITEM(rv, 0, est_zone_capi);
+    PyTuple_SET_ITEM(rv, 1, est_zone_macro);
+    PyTuple_SET_ITEM(rv, 2, est_zone_macro_noname);
+
+    return rv;
+}
+
+static PyObject *
+get_timezones_offset_zero(PyObject *self, PyObject *args)
+{
+    PyObject *offset = PyDelta_FromDSU(0, 0, 0);
+    PyObject *name = PyUnicode_FromString("");
+
+    // These two should return the UTC singleton
+    PyObject *utc_singleton_0 = PyTimeZone_FromOffset(offset);
+    PyObject *utc_singleton_1 = PyTimeZone_FromOffsetAndName(offset, NULL);
+
+    // This one will return +00:00 zone, but not the UTC singleton
+    PyObject *non_utc_zone = PyTimeZone_FromOffsetAndName(offset, name);
+
+    Py_DecRef(offset);
+    Py_DecRef(name);
+
+    PyObject *rv = PyTuple_New(3);
+    PyTuple_SET_ITEM(rv, 0, utc_singleton_0);
+    PyTuple_SET_ITEM(rv, 1, utc_singleton_1);
+    PyTuple_SET_ITEM(rv, 2, non_utc_zone);
+
+    return rv;
+}
+
+static PyObject *
+get_timezone_utc_capi(PyObject *self, PyObject *args)
+{
+    int macro = 0;
+    if (!PyArg_ParseTuple(args, "|p", &macro)) {
+        return NULL;
+    }
+    if (macro) {
+        Py_INCREF(PyDateTime_TimeZone_UTC);
+        return PyDateTime_TimeZone_UTC;
+    }
+    Py_INCREF(PyDateTimeAPI->TimeZone_UTC);
+    return PyDateTimeAPI->TimeZone_UTC;
+}
+
+static PyObject *
+get_date_fromdate(PyObject *self, PyObject *args)
+{
+    PyObject *rv = NULL;
+    int macro;
+    int year, month, day;
+
+    if (!PyArg_ParseTuple(args, "piii", &macro, &year, &month, &day)) {
+        return NULL;
+    }
+
+    if (macro) {
+        rv = PyDate_FromDate(year, month, day);
+    }
+    else {
+        rv = PyDateTimeAPI->Date_FromDate(
+                year, month, day,
+                PyDateTimeAPI->DateType);
+    }
+    return rv;
+}
+
+static PyObject *
+get_datetime_fromdateandtime(PyObject *self, PyObject *args)
+{
+    PyObject *rv = NULL;
+    int macro;
+    int year, month, day;
+    int hour, minute, second, microsecond;
+
+    if (!PyArg_ParseTuple(args, "piiiiiii",
+                          &macro,
+                          &year, &month, &day,
+                          &hour, &minute, &second, &microsecond)) {
+        return NULL;
+    }
+
+    if (macro) {
+        rv = PyDateTime_FromDateAndTime(
+                year, month, day,
+                hour, minute, second, microsecond);
+    }
+    else {
+        rv = PyDateTimeAPI->DateTime_FromDateAndTime(
+                year, month, day,
+                hour, minute, second, microsecond,
+                Py_None,
+                PyDateTimeAPI->DateTimeType);
+    }
+    return rv;
+}
+
+static PyObject *
+get_datetime_fromdateandtimeandfold(PyObject *self, PyObject *args)
+{
+    PyObject *rv = NULL;
+    int macro;
+    int year, month, day;
+    int hour, minute, second, microsecond, fold;
+
+    if (!PyArg_ParseTuple(args, "piiiiiiii",
+                          &macro,
+                          &year, &month, &day,
+                          &hour, &minute, &second, &microsecond,
+                          &fold)) {
+        return NULL;
+    }
+
+    if (macro) {
+        rv = PyDateTime_FromDateAndTimeAndFold(
+                year, month, day,
+                hour, minute, second, microsecond,
+                fold);
+    }
+    else {
+        rv = PyDateTimeAPI->DateTime_FromDateAndTimeAndFold(
+                year, month, day,
+                hour, minute, second, microsecond,
+                Py_None,
+                fold,
+                PyDateTimeAPI->DateTimeType);
+    }
+    return rv;
+}
+
+static PyObject *
+get_time_fromtime(PyObject *self, PyObject *args)
+{
+    PyObject *rv = NULL;
+    int macro;
+    int hour, minute, second, microsecond;
+
+    if (!PyArg_ParseTuple(args, "piiii",
+                          &macro,
+                          &hour, &minute, &second, &microsecond))
+    {
+        return NULL;
+    }
+
+    if (macro) {
+        rv = PyTime_FromTime(hour, minute, second, microsecond);
+    }
+    else {
+        rv = PyDateTimeAPI->Time_FromTime(
+                hour, minute, second, microsecond,
+                Py_None,
+                PyDateTimeAPI->TimeType);
+    }
+    return rv;
+}
+
+static PyObject *
+get_time_fromtimeandfold(PyObject *self, PyObject *args)
+{
+    PyObject *rv = NULL;
+    int macro;
+    int hour, minute, second, microsecond, fold;
+
+    if (!PyArg_ParseTuple(args, "piiiii",
+                          &macro,
+                          &hour, &minute, &second, &microsecond,
+                          &fold)) {
+        return NULL;
+    }
+
+    if (macro) {
+        rv = PyTime_FromTimeAndFold(hour, minute, second, microsecond, fold);
+    }
+    else {
+        rv = PyDateTimeAPI->Time_FromTimeAndFold(
+                hour, minute, second, microsecond,
+                Py_None,
+                fold,
+                PyDateTimeAPI->TimeType);
+    }
+    return rv;
+}
+
+static PyObject *
+get_delta_fromdsu(PyObject *self, PyObject *args)
+{
+    PyObject *rv = NULL;
+    int macro;
+    int days, seconds, microseconds;
+
+    if (!PyArg_ParseTuple(args, "piii",
+                          &macro,
+                          &days, &seconds, &microseconds)) {
+        return NULL;
+    }
+
+    if (macro) {
+        rv = PyDelta_FromDSU(days, seconds, microseconds);
+    }
+    else {
+        rv = PyDateTimeAPI->Delta_FromDelta(
+                days, seconds, microseconds, 1,
+                PyDateTimeAPI->DeltaType);
+    }
+
+    return rv;
+}
+
+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, &macro)) {
+        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, &macro)) {
+        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;
+}
+
+static PyObject *
+test_PyDateTime_GET(PyObject *self, PyObject *obj)
+{
+    int year, month, day;
+
+    year = PyDateTime_GET_YEAR(obj);
+    month = PyDateTime_GET_MONTH(obj);
+    day = PyDateTime_GET_DAY(obj);
+
+    return Py_BuildValue("(iii)", year, month, day);
+}
+
+static PyObject *
+test_PyDateTime_DATE_GET(PyObject *self, PyObject *obj)
+{
+    int hour = PyDateTime_DATE_GET_HOUR(obj);
+    int minute = PyDateTime_DATE_GET_MINUTE(obj);
+    int second = PyDateTime_DATE_GET_SECOND(obj);
+    int microsecond = PyDateTime_DATE_GET_MICROSECOND(obj);
+    PyObject *tzinfo = PyDateTime_DATE_GET_TZINFO(obj);
+
+    return Py_BuildValue("(iiiiO)", hour, minute, second, microsecond, tzinfo);
+}
+
+static PyObject *
+test_PyDateTime_TIME_GET(PyObject *self, PyObject *obj)
+{
+    int hour = PyDateTime_TIME_GET_HOUR(obj);
+    int minute = PyDateTime_TIME_GET_MINUTE(obj);
+    int second = PyDateTime_TIME_GET_SECOND(obj);
+    int microsecond = PyDateTime_TIME_GET_MICROSECOND(obj);
+    PyObject *tzinfo = PyDateTime_TIME_GET_TZINFO(obj);
+
+    return Py_BuildValue("(iiiiO)", hour, minute, second, microsecond, tzinfo);
+}
+
+static PyObject *
+test_PyDateTime_DELTA_GET(PyObject *self, PyObject *obj)
+{
+    int days = PyDateTime_DELTA_GET_DAYS(obj);
+    int seconds = PyDateTime_DELTA_GET_SECONDS(obj);
+    int microseconds = PyDateTime_DELTA_GET_MICROSECONDS(obj);
+
+    return Py_BuildValue("(iii)", days, seconds, microseconds);
+}
+
+static PyMethodDef test_methods[] = {
+    {"PyDateTime_DATE_GET",         test_PyDateTime_DATE_GET,       METH_O},
+    {"PyDateTime_DELTA_GET",        test_PyDateTime_DELTA_GET,      METH_O},
+    {"PyDateTime_GET",              test_PyDateTime_GET,            METH_O},
+    {"PyDateTime_TIME_GET",         test_PyDateTime_TIME_GET,       METH_O},
+    {"datetime_check_date",         datetime_check_date,            METH_VARARGS},
+    {"datetime_check_datetime",     datetime_check_datetime,        METH_VARARGS},
+    {"datetime_check_delta",        datetime_check_delta,           METH_VARARGS},
+    {"datetime_check_time",         datetime_check_time,            METH_VARARGS},
+    {"datetime_check_tzinfo",       datetime_check_tzinfo,          METH_VARARGS},
+    {"get_date_fromdate",           get_date_fromdate,              METH_VARARGS},
+    {"get_date_fromtimestamp",      get_date_fromtimestamp,         METH_VARARGS},
+    {"get_datetime_fromdateandtime", get_datetime_fromdateandtime,  METH_VARARGS},
+    {"get_datetime_fromdateandtimeandfold", get_datetime_fromdateandtimeandfold, METH_VARARGS},
+    {"get_datetime_fromtimestamp",  get_datetime_fromtimestamp,     METH_VARARGS},
+    {"get_delta_fromdsu",           get_delta_fromdsu,              METH_VARARGS},
+    {"get_time_fromtime",           get_time_fromtime,              METH_VARARGS},
+    {"get_time_fromtimeandfold",    get_time_fromtimeandfold,       METH_VARARGS},
+    {"get_timezone_utc_capi",       get_timezone_utc_capi,          METH_VARARGS},
+    {"get_timezones_offset_zero",   get_timezones_offset_zero,      METH_NOARGS},
+    {"make_timezones_capi",         make_timezones_capi,            METH_NOARGS},
+    {"test_datetime_capi",          test_datetime_capi,             METH_NOARGS},
+    {NULL},
+};
+
+int
+_PyTestCapi_Init_DateTime(PyObject *mod)
+{
+    if (PyModule_AddFunctions(mod, test_methods) < 0) {
+        return -1;
+    }
+    return 0;
+}
index 25ee0f76ec0216d8d4e4f852ce401e950de05309..2fa8dac4d56598a12c908b7fd867cb22d27ef46c 100644 (file)
@@ -28,6 +28,8 @@ int _PyTestCapi_Init_Vectorcall(PyObject *module);
 int _PyTestCapi_Init_Heaptype(PyObject *module);
 int _PyTestCapi_Init_Unicode(PyObject *module);
 int _PyTestCapi_Init_GetArgs(PyObject *module);
+int _PyTestCapi_Init_PyTime(PyObject *module);
+int _PyTestCapi_Init_DateTime(PyObject *module);
 
 #ifdef LIMITED_API_AVAILABLE
 int _PyTestCapi_Init_VectorcallLimited(PyObject *module);
diff --git a/Modules/_testcapi/pytime.c b/Modules/_testcapi/pytime.c
new file mode 100644 (file)
index 0000000..7422baf
--- /dev/null
@@ -0,0 +1,274 @@
+#include "parts.h"
+
+#ifdef MS_WINDOWS
+#  include <winsock2.h>           // struct timeval
+#endif
+
+static PyObject *
+test_pytime_fromseconds(PyObject *self, PyObject *args)
+{
+    int seconds;
+    if (!PyArg_ParseTuple(args, "i", &seconds)) {
+        return NULL;
+    }
+    _PyTime_t ts = _PyTime_FromSeconds(seconds);
+    return _PyTime_AsNanosecondsObject(ts);
+}
+
+static int
+check_time_rounding(int round)
+{
+    if (round != _PyTime_ROUND_FLOOR
+        && round != _PyTime_ROUND_CEILING
+        && round != _PyTime_ROUND_HALF_EVEN
+        && round != _PyTime_ROUND_UP)
+    {
+        PyErr_SetString(PyExc_ValueError, "invalid rounding");
+        return -1;
+    }
+    return 0;
+}
+
+static PyObject *
+test_pytime_fromsecondsobject(PyObject *self, PyObject *args)
+{
+    PyObject *obj;
+    int round;
+    if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
+        return NULL;
+    }
+    if (check_time_rounding(round) < 0) {
+        return NULL;
+    }
+    _PyTime_t ts;
+    if (_PyTime_FromSecondsObject(&ts, obj, round) == -1) {
+        return NULL;
+    }
+    return _PyTime_AsNanosecondsObject(ts);
+}
+
+static PyObject *
+test_pytime_assecondsdouble(PyObject *self, PyObject *args)
+{
+    PyObject *obj;
+    if (!PyArg_ParseTuple(args, "O", &obj)) {
+        return NULL;
+    }
+    _PyTime_t ts;
+    if (_PyTime_FromNanosecondsObject(&ts, obj) < 0) {
+        return NULL;
+    }
+    double d = _PyTime_AsSecondsDouble(ts);
+    return PyFloat_FromDouble(d);
+}
+
+static PyObject *
+test_PyTime_AsTimeval(PyObject *self, PyObject *args)
+{
+    PyObject *obj;
+    int round;
+    if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
+        return NULL;
+    }
+    if (check_time_rounding(round) < 0) {
+        return NULL;
+    }
+    _PyTime_t t;
+    if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
+        return NULL;
+    }
+    struct timeval tv;
+    if (_PyTime_AsTimeval(t, &tv, round) < 0) {
+        return NULL;
+    }
+
+    PyObject *seconds = PyLong_FromLongLong(tv.tv_sec);
+    if (seconds == NULL) {
+        return NULL;
+    }
+    return Py_BuildValue("Nl", seconds, (long)tv.tv_usec);
+}
+
+static PyObject *
+test_PyTime_AsTimeval_clamp(PyObject *self, PyObject *args)
+{
+    PyObject *obj;
+    int round;
+    if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
+        return NULL;
+    }
+    if (check_time_rounding(round) < 0) {
+        return NULL;
+    }
+    _PyTime_t t;
+    if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
+        return NULL;
+    }
+    struct timeval tv;
+    _PyTime_AsTimeval_clamp(t, &tv, round);
+
+    PyObject *seconds = PyLong_FromLongLong(tv.tv_sec);
+    if (seconds == NULL) {
+        return NULL;
+    }
+    return Py_BuildValue("Nl", seconds, (long)tv.tv_usec);
+}
+
+#ifdef HAVE_CLOCK_GETTIME
+static PyObject *
+test_PyTime_AsTimespec(PyObject *self, PyObject *args)
+{
+    PyObject *obj;
+    if (!PyArg_ParseTuple(args, "O", &obj)) {
+        return NULL;
+    }
+    _PyTime_t t;
+    if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
+        return NULL;
+    }
+    struct timespec ts;
+    if (_PyTime_AsTimespec(t, &ts) == -1) {
+        return NULL;
+    }
+    return Py_BuildValue("Nl", _PyLong_FromTime_t(ts.tv_sec), ts.tv_nsec);
+}
+
+static PyObject *
+test_PyTime_AsTimespec_clamp(PyObject *self, PyObject *args)
+{
+    PyObject *obj;
+    if (!PyArg_ParseTuple(args, "O", &obj)) {
+        return NULL;
+    }
+    _PyTime_t t;
+    if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
+        return NULL;
+    }
+    struct timespec ts;
+    _PyTime_AsTimespec_clamp(t, &ts);
+    return Py_BuildValue("Nl", _PyLong_FromTime_t(ts.tv_sec), ts.tv_nsec);
+}
+#endif
+
+static PyObject *
+test_PyTime_AsMilliseconds(PyObject *self, PyObject *args)
+{
+    PyObject *obj;
+    int round;
+    if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
+        return NULL;
+    }
+    _PyTime_t t;
+    if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
+        return NULL;
+    }
+    if (check_time_rounding(round) < 0) {
+        return NULL;
+    }
+    _PyTime_t ms = _PyTime_AsMilliseconds(t, round);
+    _PyTime_t ns = _PyTime_FromNanoseconds(ms);
+    return _PyTime_AsNanosecondsObject(ns);
+}
+
+static PyObject *
+test_PyTime_AsMicroseconds(PyObject *self, PyObject *args)
+{
+    PyObject *obj;
+    int round;
+    if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
+        return NULL;
+    }
+    _PyTime_t t;
+    if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
+        return NULL;
+    }
+    if (check_time_rounding(round) < 0) {
+        return NULL;
+    }
+    _PyTime_t us = _PyTime_AsMicroseconds(t, round);
+    _PyTime_t ns = _PyTime_FromNanoseconds(us);
+    return _PyTime_AsNanosecondsObject(ns);
+}
+
+static PyObject *
+test_pytime_object_to_time_t(PyObject *self, PyObject *args)
+{
+    PyObject *obj;
+    time_t sec;
+    int round;
+    if (!PyArg_ParseTuple(args, "Oi:pytime_object_to_time_t", &obj, &round)) {
+        return NULL;
+    }
+    if (check_time_rounding(round) < 0) {
+        return NULL;
+    }
+    if (_PyTime_ObjectToTime_t(obj, &sec, round) == -1) {
+        return NULL;
+    }
+    return _PyLong_FromTime_t(sec);
+}
+
+static PyObject *
+test_pytime_object_to_timeval(PyObject *self, PyObject *args)
+{
+    PyObject *obj;
+    time_t sec;
+    long usec;
+    int round;
+    if (!PyArg_ParseTuple(args, "Oi:pytime_object_to_timeval", &obj, &round)) {
+        return NULL;
+    }
+    if (check_time_rounding(round) < 0) {
+        return NULL;
+    }
+    if (_PyTime_ObjectToTimeval(obj, &sec, &usec, round) == -1) {
+        return NULL;
+    }
+    return Py_BuildValue("Nl", _PyLong_FromTime_t(sec), usec);
+}
+
+static PyObject *
+test_pytime_object_to_timespec(PyObject *self, PyObject *args)
+{
+    PyObject *obj;
+    time_t sec;
+    long nsec;
+    int round;
+    if (!PyArg_ParseTuple(args, "Oi:pytime_object_to_timespec", &obj, &round)) {
+        return NULL;
+    }
+    if (check_time_rounding(round) < 0) {
+        return NULL;
+    }
+    if (_PyTime_ObjectToTimespec(obj, &sec, &nsec, round) == -1) {
+        return NULL;
+    }
+    return Py_BuildValue("Nl", _PyLong_FromTime_t(sec), nsec);
+}
+
+static PyMethodDef test_methods[] = {
+    {"PyTime_AsMicroseconds",       test_PyTime_AsMicroseconds,     METH_VARARGS},
+    {"PyTime_AsMilliseconds",       test_PyTime_AsMilliseconds,     METH_VARARGS},
+    {"PyTime_AsSecondsDouble",      test_pytime_assecondsdouble,    METH_VARARGS},
+#ifdef HAVE_CLOCK_GETTIME
+    {"PyTime_AsTimespec",           test_PyTime_AsTimespec,         METH_VARARGS},
+    {"PyTime_AsTimespec_clamp",     test_PyTime_AsTimespec_clamp,   METH_VARARGS},
+#endif
+    {"PyTime_AsTimeval",            test_PyTime_AsTimeval,          METH_VARARGS},
+    {"PyTime_AsTimeval_clamp",      test_PyTime_AsTimeval_clamp,    METH_VARARGS},
+    {"PyTime_FromSeconds",          test_pytime_fromseconds,        METH_VARARGS},
+    {"PyTime_FromSecondsObject",    test_pytime_fromsecondsobject,  METH_VARARGS},
+    {"pytime_object_to_time_t",     test_pytime_object_to_time_t,   METH_VARARGS},
+    {"pytime_object_to_timespec",   test_pytime_object_to_timespec, METH_VARARGS},
+    {"pytime_object_to_timeval",    test_pytime_object_to_timeval,  METH_VARARGS},
+    {NULL},
+};
+
+int
+_PyTestCapi_Init_PyTime(PyObject *mod)
+{
+    if (PyModule_AddFunctions(mod, test_methods) < 0) {
+        return -1;
+    }
+    return 0;
+}
index 0ab0b846180fc8c0b8fd8def27a40ac6544051e6..79beb1c2e3a82f5345429a845ec087a591584ee3 100644 (file)
 #define PY_SSIZE_T_CLEAN
 
 #include "Python.h"
-#include "datetime.h"             // PyDateTimeAPI
 #include "marshal.h"              // PyMarshal_WriteLongToFile
 #include "structmember.h"         // PyMemberDef
 #include <float.h>                // FLT_MAX
 #include <signal.h>
 
-#ifdef MS_WINDOWS
-#  include <winsock2.h>           // struct timeval
-#endif
-
 #ifdef HAVE_SYS_WAIT_H
 #include <sys/wait.h>             // W_STOPCODE
 #endif
@@ -1326,411 +1321,6 @@ test_set_exc_info(PyObject *self, PyObject *args)
     return orig_exc;
 }
 
-static int test_run_counter = 0;
-
-static PyObject *
-test_datetime_capi(PyObject *self, PyObject *args) {
-    if (PyDateTimeAPI) {
-        if (test_run_counter) {
-            /* Probably regrtest.py -R */
-            Py_RETURN_NONE;
-        }
-        else {
-            PyErr_SetString(PyExc_AssertionError,
-                            "PyDateTime_CAPI somehow initialized");
-            return NULL;
-        }
-    }
-    test_run_counter++;
-    PyDateTime_IMPORT;
-
-    if (PyDateTimeAPI)
-        Py_RETURN_NONE;
-    else
-        return NULL;
-}
-
-/* Functions exposing the C API type checking for testing */
-#define MAKE_DATETIME_CHECK_FUNC(check_method, exact_method)    \
-    PyObject *obj;                                              \
-    int exact = 0;                                              \
-    if (!PyArg_ParseTuple(args, "O|p", &obj, &exact)) {         \
-        return NULL;                                            \
-    }                                                           \
-    int rv = exact?exact_method(obj):check_method(obj);         \
-    if (rv) {                                                   \
-        Py_RETURN_TRUE;                                         \
-    } else {                                                    \
-        Py_RETURN_FALSE;                                        \
-    }
-
-static PyObject *
-datetime_check_date(PyObject *self, PyObject *args) {
-    MAKE_DATETIME_CHECK_FUNC(PyDate_Check, PyDate_CheckExact)
-}
-
-static PyObject *
-datetime_check_time(PyObject *self, PyObject *args) {
-    MAKE_DATETIME_CHECK_FUNC(PyTime_Check, PyTime_CheckExact)
-}
-
-static PyObject *
-datetime_check_datetime(PyObject *self, PyObject *args) {
-    MAKE_DATETIME_CHECK_FUNC(PyDateTime_Check, PyDateTime_CheckExact)
-}
-
-static PyObject *
-datetime_check_delta(PyObject *self, PyObject *args) {
-    MAKE_DATETIME_CHECK_FUNC(PyDelta_Check, PyDelta_CheckExact)
-}
-
-static PyObject *
-datetime_check_tzinfo(PyObject *self, PyObject *args) {
-    MAKE_DATETIME_CHECK_FUNC(PyTZInfo_Check, PyTZInfo_CheckExact)
-}
-
-
-/* Makes three variations on timezone representing UTC-5:
-   1. timezone with offset and name from PyDateTimeAPI
-   2. timezone with offset and name from PyTimeZone_FromOffsetAndName
-   3. timezone with offset (no name) from PyTimeZone_FromOffset
-*/
-static PyObject *
-make_timezones_capi(PyObject *self, PyObject *args) {
-    PyObject *offset = PyDelta_FromDSU(0, -18000, 0);
-    PyObject *name = PyUnicode_FromString("EST");
-
-    PyObject *est_zone_capi = PyDateTimeAPI->TimeZone_FromTimeZone(offset, name);
-    PyObject *est_zone_macro = PyTimeZone_FromOffsetAndName(offset, name);
-    PyObject *est_zone_macro_noname = PyTimeZone_FromOffset(offset);
-
-    Py_DecRef(offset);
-    Py_DecRef(name);
-
-    PyObject *rv = PyTuple_New(3);
-
-    PyTuple_SET_ITEM(rv, 0, est_zone_capi);
-    PyTuple_SET_ITEM(rv, 1, est_zone_macro);
-    PyTuple_SET_ITEM(rv, 2, est_zone_macro_noname);
-
-    return rv;
-}
-
-static PyObject *
-get_timezones_offset_zero(PyObject *self, PyObject *args) {
-    PyObject *offset = PyDelta_FromDSU(0, 0, 0);
-    PyObject *name = PyUnicode_FromString("");
-
-    // These two should return the UTC singleton
-    PyObject *utc_singleton_0 = PyTimeZone_FromOffset(offset);
-    PyObject *utc_singleton_1 = PyTimeZone_FromOffsetAndName(offset, NULL);
-
-    // This one will return +00:00 zone, but not the UTC singleton
-    PyObject *non_utc_zone = PyTimeZone_FromOffsetAndName(offset, name);
-
-    Py_DecRef(offset);
-    Py_DecRef(name);
-
-    PyObject *rv = PyTuple_New(3);
-    PyTuple_SET_ITEM(rv, 0, utc_singleton_0);
-    PyTuple_SET_ITEM(rv, 1, utc_singleton_1);
-    PyTuple_SET_ITEM(rv, 2, non_utc_zone);
-
-    return rv;
-}
-
-static PyObject *
-get_timezone_utc_capi(PyObject* self, PyObject *args) {
-    int macro = 0;
-    if (!PyArg_ParseTuple(args, "|p", &macro)) {
-        return NULL;
-    }
-    if (macro) {
-        return Py_NewRef(PyDateTime_TimeZone_UTC);
-    } else {
-        return Py_NewRef(PyDateTimeAPI->TimeZone_UTC);
-    }
-}
-
-static PyObject *
-get_date_fromdate(PyObject *self, PyObject *args)
-{
-    PyObject *rv = NULL;
-    int macro;
-    int year, month, day;
-
-    if (!PyArg_ParseTuple(args, "piii", &macro, &year, &month, &day)) {
-        return NULL;
-    }
-
-    if (macro) {
-        rv = PyDate_FromDate(year, month, day);
-    }
-    else {
-        rv = PyDateTimeAPI->Date_FromDate(
-            year, month, day,
-            PyDateTimeAPI->DateType);
-    }
-    return rv;
-}
-
-static PyObject *
-get_datetime_fromdateandtime(PyObject *self, PyObject *args)
-{
-    PyObject *rv = NULL;
-    int macro;
-    int year, month, day;
-    int hour, minute, second, microsecond;
-
-    if (!PyArg_ParseTuple(args, "piiiiiii",
-                          &macro,
-                          &year, &month, &day,
-                          &hour, &minute, &second, &microsecond)) {
-        return NULL;
-    }
-
-    if (macro) {
-        rv = PyDateTime_FromDateAndTime(
-            year, month, day,
-            hour, minute, second, microsecond);
-    }
-    else {
-        rv = PyDateTimeAPI->DateTime_FromDateAndTime(
-            year, month, day,
-            hour, minute, second, microsecond,
-            Py_None,
-            PyDateTimeAPI->DateTimeType);
-    }
-    return rv;
-}
-
-static PyObject *
-get_datetime_fromdateandtimeandfold(PyObject *self, PyObject *args)
-{
-    PyObject *rv = NULL;
-    int macro;
-    int year, month, day;
-    int hour, minute, second, microsecond, fold;
-
-    if (!PyArg_ParseTuple(args, "piiiiiiii",
-                          &macro,
-                          &year, &month, &day,
-                          &hour, &minute, &second, &microsecond,
-                          &fold)) {
-        return NULL;
-    }
-
-    if (macro) {
-        rv = PyDateTime_FromDateAndTimeAndFold(
-            year, month, day,
-            hour, minute, second, microsecond,
-            fold);
-    }
-    else {
-        rv = PyDateTimeAPI->DateTime_FromDateAndTimeAndFold(
-            year, month, day,
-            hour, minute, second, microsecond,
-            Py_None,
-            fold,
-            PyDateTimeAPI->DateTimeType);
-    }
-    return rv;
-}
-
-static PyObject *
-get_time_fromtime(PyObject *self, PyObject *args)
-{
-    PyObject *rv = NULL;
-    int macro;
-    int hour, minute, second, microsecond;
-
-    if (!PyArg_ParseTuple(args, "piiii",
-                          &macro,
-                          &hour, &minute, &second, &microsecond)) {
-        return NULL;
-    }
-
-    if (macro) {
-        rv = PyTime_FromTime(hour, minute, second, microsecond);
-    }
-    else {
-        rv = PyDateTimeAPI->Time_FromTime(
-            hour, minute, second, microsecond,
-            Py_None,
-            PyDateTimeAPI->TimeType);
-    }
-    return rv;
-}
-
-static PyObject *
-get_time_fromtimeandfold(PyObject *self, PyObject *args)
-{
-    PyObject *rv = NULL;
-    int macro;
-    int hour, minute, second, microsecond, fold;
-
-    if (!PyArg_ParseTuple(args, "piiiii",
-                          &macro,
-                          &hour, &minute, &second, &microsecond,
-                          &fold)) {
-        return NULL;
-    }
-
-    if (macro) {
-        rv = PyTime_FromTimeAndFold(hour, minute, second, microsecond, fold);
-    }
-    else {
-        rv = PyDateTimeAPI->Time_FromTimeAndFold(
-            hour, minute, second, microsecond,
-            Py_None,
-            fold,
-            PyDateTimeAPI->TimeType);
-    }
-    return rv;
-}
-
-static PyObject *
-get_delta_fromdsu(PyObject *self, PyObject *args)
-{
-    PyObject *rv = NULL;
-    int macro;
-    int days, seconds, microseconds;
-
-    if (!PyArg_ParseTuple(args, "piii",
-                          &macro,
-                          &days, &seconds, &microseconds)) {
-        return NULL;
-    }
-
-    if (macro) {
-        rv = PyDelta_FromDSU(days, seconds, microseconds);
-    }
-    else {
-        rv = PyDateTimeAPI->Delta_FromDelta(
-            days, seconds, microseconds, 1,
-            PyDateTimeAPI->DeltaType);
-    }
-
-    return rv;
-}
-
-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, &macro)) {
-        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, &macro)) {
-        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;
-}
-
-static PyObject *
-test_PyDateTime_GET(PyObject *self, PyObject *obj)
-{
-    int year, month, day;
-
-    year = PyDateTime_GET_YEAR(obj);
-    month = PyDateTime_GET_MONTH(obj);
-    day = PyDateTime_GET_DAY(obj);
-
-    return Py_BuildValue("(iii)", year, month, day);
-}
-
-static PyObject *
-test_PyDateTime_DATE_GET(PyObject *self, PyObject *obj)
-{
-    int hour, minute, second, microsecond;
-
-    hour = PyDateTime_DATE_GET_HOUR(obj);
-    minute = PyDateTime_DATE_GET_MINUTE(obj);
-    second = PyDateTime_DATE_GET_SECOND(obj);
-    microsecond = PyDateTime_DATE_GET_MICROSECOND(obj);
-    PyObject *tzinfo = PyDateTime_DATE_GET_TZINFO(obj);
-
-    return Py_BuildValue("(iiiiO)", hour, minute, second, microsecond, tzinfo);
-}
-
-static PyObject *
-test_PyDateTime_TIME_GET(PyObject *self, PyObject *obj)
-{
-    int hour, minute, second, microsecond;
-
-    hour = PyDateTime_TIME_GET_HOUR(obj);
-    minute = PyDateTime_TIME_GET_MINUTE(obj);
-    second = PyDateTime_TIME_GET_SECOND(obj);
-    microsecond = PyDateTime_TIME_GET_MICROSECOND(obj);
-    PyObject *tzinfo = PyDateTime_TIME_GET_TZINFO(obj);
-
-    return Py_BuildValue("(iiiiO)", hour, minute, second, microsecond, tzinfo);
-}
-
-static PyObject *
-test_PyDateTime_DELTA_GET(PyObject *self, PyObject *obj)
-{
-    int days, seconds, microseconds;
-
-    days = PyDateTime_DELTA_GET_DAYS(obj);
-    seconds = PyDateTime_DELTA_GET_SECONDS(obj);
-    microseconds = PyDateTime_DELTA_GET_MICROSECONDS(obj);
-
-    return Py_BuildValue("(iii)", days, seconds, microseconds);
-}
-
 /* 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
  * thread finishes, because the thread uses a PyObject (the callable) that
@@ -2544,66 +2134,6 @@ run_in_subinterp_with_config(PyObject *self, PyObject *args, PyObject *kwargs)
     return PyLong_FromLong(r);
 }
 
-static int
-check_time_rounding(int round)
-{
-    if (round != _PyTime_ROUND_FLOOR
-        && round != _PyTime_ROUND_CEILING
-        && round != _PyTime_ROUND_HALF_EVEN
-        && round != _PyTime_ROUND_UP) {
-        PyErr_SetString(PyExc_ValueError, "invalid rounding");
-        return -1;
-    }
-    return 0;
-}
-
-static PyObject *
-test_pytime_object_to_time_t(PyObject *self, PyObject *args)
-{
-    PyObject *obj;
-    time_t sec;
-    int round;
-    if (!PyArg_ParseTuple(args, "Oi:pytime_object_to_time_t", &obj, &round))
-        return NULL;
-    if (check_time_rounding(round) < 0)
-        return NULL;
-    if (_PyTime_ObjectToTime_t(obj, &sec, round) == -1)
-        return NULL;
-    return _PyLong_FromTime_t(sec);
-}
-
-static PyObject *
-test_pytime_object_to_timeval(PyObject *self, PyObject *args)
-{
-    PyObject *obj;
-    time_t sec;
-    long usec;
-    int round;
-    if (!PyArg_ParseTuple(args, "Oi:pytime_object_to_timeval", &obj, &round))
-        return NULL;
-    if (check_time_rounding(round) < 0)
-        return NULL;
-    if (_PyTime_ObjectToTimeval(obj, &sec, &usec, round) == -1)
-        return NULL;
-    return Py_BuildValue("Nl", _PyLong_FromTime_t(sec), usec);
-}
-
-static PyObject *
-test_pytime_object_to_timespec(PyObject *self, PyObject *args)
-{
-    PyObject *obj;
-    time_t sec;
-    long nsec;
-    int round;
-    if (!PyArg_ParseTuple(args, "Oi:pytime_object_to_timespec", &obj, &round))
-        return NULL;
-    if (check_time_rounding(round) < 0)
-        return NULL;
-    if (_PyTime_ObjectToTimespec(obj, &sec, &nsec, round) == -1)
-        return NULL;
-    return Py_BuildValue("Nl", _PyLong_FromTime_t(sec), nsec);
-}
-
 static void
 slot_tp_del(PyObject *self)
 {
@@ -3539,178 +3069,6 @@ getitem_with_error(PyObject *self, PyObject *args)
     return PyObject_GetItem(map, key);
 }
 
-static PyObject *
-test_pytime_fromseconds(PyObject *self, PyObject *args)
-{
-    int seconds;
-    if (!PyArg_ParseTuple(args, "i", &seconds)) {
-        return NULL;
-    }
-    _PyTime_t ts = _PyTime_FromSeconds(seconds);
-    return _PyTime_AsNanosecondsObject(ts);
-}
-
-static PyObject *
-test_pytime_fromsecondsobject(PyObject *self, PyObject *args)
-{
-    PyObject *obj;
-    int round;
-    if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
-        return NULL;
-    }
-    if (check_time_rounding(round) < 0) {
-        return NULL;
-    }
-    _PyTime_t ts;
-    if (_PyTime_FromSecondsObject(&ts, obj, round) == -1) {
-        return NULL;
-    }
-    return _PyTime_AsNanosecondsObject(ts);
-}
-
-static PyObject *
-test_pytime_assecondsdouble(PyObject *self, PyObject *args)
-{
-    PyObject *obj;
-    if (!PyArg_ParseTuple(args, "O", &obj)) {
-        return NULL;
-    }
-    _PyTime_t ts;
-    if (_PyTime_FromNanosecondsObject(&ts, obj) < 0) {
-        return NULL;
-    }
-    double d = _PyTime_AsSecondsDouble(ts);
-    return PyFloat_FromDouble(d);
-}
-
-static PyObject *
-test_PyTime_AsTimeval(PyObject *self, PyObject *args)
-{
-    PyObject *obj;
-    int round;
-    if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
-        return NULL;
-    }
-    if (check_time_rounding(round) < 0) {
-        return NULL;
-    }
-    _PyTime_t t;
-    if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
-        return NULL;
-    }
-    struct timeval tv;
-    if (_PyTime_AsTimeval(t, &tv, round) < 0) {
-        return NULL;
-    }
-
-    PyObject *seconds = PyLong_FromLongLong(tv.tv_sec);
-    if (seconds == NULL) {
-        return NULL;
-    }
-    return Py_BuildValue("Nl", seconds, (long)tv.tv_usec);
-}
-
-static PyObject *
-test_PyTime_AsTimeval_clamp(PyObject *self, PyObject *args)
-{
-    PyObject *obj;
-    int round;
-    if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
-        return NULL;
-    }
-    if (check_time_rounding(round) < 0) {
-        return NULL;
-    }
-    _PyTime_t t;
-    if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
-        return NULL;
-    }
-    struct timeval tv;
-    _PyTime_AsTimeval_clamp(t, &tv, round);
-
-    PyObject *seconds = PyLong_FromLongLong(tv.tv_sec);
-    if (seconds == NULL) {
-        return NULL;
-    }
-    return Py_BuildValue("Nl", seconds, (long)tv.tv_usec);
-}
-
-#ifdef HAVE_CLOCK_GETTIME
-static PyObject *
-test_PyTime_AsTimespec(PyObject *self, PyObject *args)
-{
-    PyObject *obj;
-    if (!PyArg_ParseTuple(args, "O", &obj)) {
-        return NULL;
-    }
-    _PyTime_t t;
-    if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
-        return NULL;
-    }
-    struct timespec ts;
-    if (_PyTime_AsTimespec(t, &ts) == -1) {
-        return NULL;
-    }
-    return Py_BuildValue("Nl", _PyLong_FromTime_t(ts.tv_sec), ts.tv_nsec);
-}
-
-static PyObject *
-test_PyTime_AsTimespec_clamp(PyObject *self, PyObject *args)
-{
-    PyObject *obj;
-    if (!PyArg_ParseTuple(args, "O", &obj)) {
-        return NULL;
-    }
-    _PyTime_t t;
-    if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
-        return NULL;
-    }
-    struct timespec ts;
-    _PyTime_AsTimespec_clamp(t, &ts);
-    return Py_BuildValue("Nl", _PyLong_FromTime_t(ts.tv_sec), ts.tv_nsec);
-}
-#endif
-
-static PyObject *
-test_PyTime_AsMilliseconds(PyObject *self, PyObject *args)
-{
-    PyObject *obj;
-    int round;
-    if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
-        return NULL;
-    }
-    _PyTime_t t;
-    if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
-        return NULL;
-    }
-    if (check_time_rounding(round) < 0) {
-        return NULL;
-    }
-    _PyTime_t ms = _PyTime_AsMilliseconds(t, round);
-    _PyTime_t ns = _PyTime_FromNanoseconds(ms);
-    return _PyTime_AsNanosecondsObject(ns);
-}
-
-static PyObject *
-test_PyTime_AsMicroseconds(PyObject *self, PyObject *args)
-{
-    PyObject *obj;
-    int round;
-    if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
-        return NULL;
-    }
-    _PyTime_t t;
-    if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
-        return NULL;
-    }
-    if (check_time_rounding(round) < 0) {
-        return NULL;
-    }
-    _PyTime_t us = _PyTime_AsMicroseconds(t, round);
-    _PyTime_t ns = _PyTime_FromNanoseconds(us);
-    return _PyTime_AsNanosecondsObject(ns);
-}
-
 static PyObject*
 pymem_buffer_overflow(PyObject *self, PyObject *args)
 {
@@ -5376,27 +4734,6 @@ static PyMethodDef TestMethods[] = {
     {"set_errno",               set_errno,                       METH_VARARGS},
     {"test_config",             test_config,                     METH_NOARGS},
     {"test_sizeof_c_types",     test_sizeof_c_types,             METH_NOARGS},
-    {"test_datetime_capi",      test_datetime_capi,              METH_NOARGS},
-    {"datetime_check_date",     datetime_check_date,             METH_VARARGS},
-    {"datetime_check_time",     datetime_check_time,             METH_VARARGS},
-    {"datetime_check_datetime",     datetime_check_datetime,     METH_VARARGS},
-    {"datetime_check_delta",     datetime_check_delta,           METH_VARARGS},
-    {"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_date_fromdate",        get_date_fromdate,              METH_VARARGS},
-    {"get_datetime_fromdateandtime", get_datetime_fromdateandtime, METH_VARARGS},
-    {"get_datetime_fromdateandtimeandfold", get_datetime_fromdateandtimeandfold, METH_VARARGS},
-    {"get_time_fromtime",        get_time_fromtime,              METH_VARARGS},
-    {"get_time_fromtimeandfold", get_time_fromtimeandfold,       METH_VARARGS},
-    {"get_delta_fromdsu",        get_delta_fromdsu,              METH_VARARGS},
-    {"get_date_fromtimestamp",   get_date_fromtimestamp,         METH_VARARGS},
-    {"get_datetime_fromtimestamp", get_datetime_fromtimestamp,   METH_VARARGS},
-    {"PyDateTime_GET",             test_PyDateTime_GET,           METH_O},
-    {"PyDateTime_DATE_GET",        test_PyDateTime_DATE_GET,      METH_O},
-    {"PyDateTime_TIME_GET",        test_PyDateTime_TIME_GET,      METH_O},
-    {"PyDateTime_DELTA_GET",       test_PyDateTime_DELTA_GET,     METH_O},
     {"test_gc_control",         test_gc_control,                 METH_NOARGS},
     {"test_list_api",           test_list_api,                   METH_NOARGS},
     {"test_dict_iteration",     test_dict_iteration,             METH_NOARGS},
@@ -5458,9 +4795,6 @@ static PyMethodDef TestMethods[] = {
     {"run_in_subinterp_with_config",
      _PyCFunction_CAST(run_in_subinterp_with_config),
      METH_VARARGS | METH_KEYWORDS},
-    {"pytime_object_to_time_t", test_pytime_object_to_time_t,  METH_VARARGS},
-    {"pytime_object_to_timeval", test_pytime_object_to_timeval,  METH_VARARGS},
-    {"pytime_object_to_timespec", test_pytime_object_to_timespec,  METH_VARARGS},
     {"with_tp_del",             with_tp_del,                     METH_VARARGS},
     {"create_cfunction",        create_cfunction,                METH_NOARGS},
     {"test_pymem_alloc0",       test_pymem_alloc0,               METH_NOARGS},
@@ -5516,17 +4850,6 @@ static PyMethodDef TestMethods[] = {
     {"return_result_with_error", return_result_with_error, METH_NOARGS},
     {"getitem_with_error", getitem_with_error, METH_VARARGS},
     {"Py_CompileString",     pycompilestring, METH_O},
-    {"PyTime_FromSeconds", test_pytime_fromseconds,  METH_VARARGS},
-    {"PyTime_FromSecondsObject", test_pytime_fromsecondsobject,  METH_VARARGS},
-    {"PyTime_AsSecondsDouble", test_pytime_assecondsdouble, METH_VARARGS},
-    {"PyTime_AsTimeval", test_PyTime_AsTimeval, METH_VARARGS},
-    {"PyTime_AsTimeval_clamp", test_PyTime_AsTimeval_clamp, METH_VARARGS},
-#ifdef HAVE_CLOCK_GETTIME
-    {"PyTime_AsTimespec", test_PyTime_AsTimespec, METH_VARARGS},
-    {"PyTime_AsTimespec_clamp", test_PyTime_AsTimespec_clamp, METH_VARARGS},
-#endif
-    {"PyTime_AsMilliseconds", test_PyTime_AsMilliseconds, METH_VARARGS},
-    {"PyTime_AsMicroseconds", test_PyTime_AsMicroseconds, METH_VARARGS},
     {"pymem_buffer_overflow", pymem_buffer_overflow, METH_NOARGS},
     {"pymem_api_misuse", pymem_api_misuse, METH_NOARGS},
     {"pymem_malloc_without_gil", pymem_malloc_without_gil, METH_NOARGS},
@@ -6431,6 +5754,12 @@ PyInit__testcapi(void)
     if (_PyTestCapi_Init_GetArgs(m) < 0) {
         return NULL;
     }
+    if (_PyTestCapi_Init_PyTime(m) < 0) {
+        return NULL;
+    }
+    if (_PyTestCapi_Init_DateTime(m) < 0) {
+        return NULL;
+    }
 
 #ifndef LIMITED_API_AVAILABLE
     PyModule_AddObjectRef(m, "LIMITED_API_AVAILABLE", Py_False);
index fc9e1591330fb4991348a1d2e705436f9a8e3d89..90b951cef90ef80cb5a998b9c83712ae6c4853b6 100644 (file)
@@ -99,6 +99,8 @@
     <ClCompile Include="..\Modules\_testcapi\vectorcall_limited.c" />
     <ClCompile Include="..\Modules\_testcapi\heaptype.c" />
     <ClCompile Include="..\Modules\_testcapi\unicode.c" />
+    <ClCompile Include="..\Modules\_testcapi\pytime.c" />
+    <ClCompile Include="..\Modules\_testcapi\datetime.c" />
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="..\PC\python_nt.rc" />
index fd936a69d2848933d7ca487965ca229304adc0f9..504898d0799fd5651c901fd16c5590febe11b760 100644 (file)
     <ClCompile Include="..\Modules\_testcapi\unicode.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\Modules\_testcapi\pytime.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\Modules\_testcapi\datetime.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="..\PC\python_nt.rc">