mirror of https://github.com/python/cpython
gh-93649: Split pytime and datetime tests from _testcapimodule.c (#99494)
This commit is contained in:
parent
1df0752b4d
commit
ee821dcd39
|
@ -169,7 +169,7 @@
|
|||
@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*
|
||||
|
|
|
@ -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", ¯o)) {
|
||||
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", ¯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;
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -20,16 +20,11 @@
|
|||
#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", ¯o)) {
|
||||
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", ¯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, 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);
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -27,6 +27,12 @@
|
|||
<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">
|
||||
|
|
Loading…
Reference in New Issue