mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 10:26:02 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			451 lines
		
	
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			451 lines
		
	
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #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", ¯o)) {
 | |
|         return NULL;
 | |
|     }
 | |
|     if (macro) {
 | |
|         return Py_NewRef(PyDateTime_TimeZone_UTC);
 | |
|     }
 | |
|     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", ¯o, &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",
 | |
|                           ¯o,
 | |
|                           &year, &month, &day,
 | |
|                           &hour, &minute, &second, µsecond)) {
 | |
|         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",
 | |
|                           ¯o,
 | |
|                           &year, &month, &day,
 | |
|                           &hour, &minute, &second, µsecond,
 | |
|                           &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",
 | |
|                           ¯o,
 | |
|                           &hour, &minute, &second, µsecond))
 | |
|     {
 | |
|         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",
 | |
|                           ¯o,
 | |
|                           &hour, &minute, &second, µsecond,
 | |
|                           &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",
 | |
|                           ¯o,
 | |
|                           &days, &seconds, µseconds)) {
 | |
|         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, ¯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;
 | |
| }
 | |
| 
 | |
| 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;
 | |
| }
 | 
