changeset: 95408:d976683671ba user: Victor Stinner date: Fri Apr 03 13:10:54 2015 +0200 files: Include/pytime.h Lib/test/test_time.py Modules/_testcapimodule.c Modules/_threadmodule.c Python/pylifecycle.c Python/pytime.c description: Issue #22117: Add a new _PyTime_FromSeconds() function Fix also _Py_InitializeEx_Private(): initialize time before initializing import, import_init() uses the _PyTime API (for thread locks). diff -r f80d5faa60ee -r d976683671ba Include/pytime.h --- a/Include/pytime.h Fri Apr 03 11:09:08 2015 +0200 +++ b/Include/pytime.h Fri Apr 03 13:10:54 2015 +0200 @@ -66,7 +66,10 @@ _PyTime_round_t); -/* Create a timestamp from a number of nanoseconds (C long). */ +/* Create a timestamp from a number of seconds. */ +PyAPI_FUNC(_PyTime_t) _PyTime_FromSeconds(int ns); + +/* Create a timestamp from a number of nanoseconds. */ PyAPI_FUNC(_PyTime_t) _PyTime_FromNanoseconds(PY_LONG_LONG ns); /* Convert a number of seconds (Python float or int) to a timetamp. diff -r f80d5faa60ee -r d976683671ba Lib/test/test_time.py --- a/Lib/test/test_time.py Fri Apr 03 11:09:08 2015 +0200 +++ b/Lib/test/test_time.py Fri Apr 03 13:10:54 2015 +0200 @@ -731,6 +731,13 @@ @unittest.skipUnless(_testcapi is not None, 'need the _testcapi module') class TestPyTime_t(unittest.TestCase): + def test_FromSeconds(self): + from _testcapi import PyTime_FromSeconds + for seconds in (0, 3, -456, _testcapi.INT_MAX, _testcapi.INT_MIN): + with self.subTest(seconds=seconds): + self.assertEqual(PyTime_FromSeconds(seconds), + seconds * SEC_TO_NS) + def test_FromSecondsObject(self): from _testcapi import PyTime_FromSecondsObject diff -r f80d5faa60ee -r d976683671ba Modules/_testcapimodule.c --- a/Modules/_testcapimodule.c Fri Apr 03 11:09:08 2015 +0200 +++ b/Modules/_testcapimodule.c Fri Apr 03 13:10:54 2015 +0200 @@ -3383,6 +3383,18 @@ } static PyObject * +test_pytime_fromseconds(PyObject *self, PyObject *args) +{ + int seconds; + _PyTime_t ts; + + if (!PyArg_ParseTuple(args, "i", &seconds)) + return NULL; + ts = _PyTime_FromSeconds(seconds); + return _PyTime_AsNanosecondsObject(ts); +} + +static PyObject * test_pytime_fromsecondsobject(PyObject *self, PyObject *args) { PyObject *obj; @@ -3651,6 +3663,7 @@ return_null_without_error, METH_NOARGS}, {"return_result_with_error", return_result_with_error, METH_NOARGS}, + {"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}, diff -r f80d5faa60ee -r d976683671ba Modules/_threadmodule.c --- a/Modules/_threadmodule.c Fri Apr 03 11:09:08 2015 +0200 +++ b/Modules/_threadmodule.c Fri Apr 03 13:10:54 2015 +0200 @@ -101,7 +101,7 @@ char *kwlist[] = {"blocking", "timeout", NULL}; int blocking = 1; PyObject *timeout_obj = NULL; - const _PyTime_t unset_timeout = _PyTime_FromNanoseconds(-1000000000); + const _PyTime_t unset_timeout = _PyTime_FromSeconds(-1); *timeout = unset_timeout ; diff -r f80d5faa60ee -r d976683671ba Python/pylifecycle.c --- a/Python/pylifecycle.c Fri Apr 03 11:09:08 2015 +0200 +++ b/Python/pylifecycle.c Fri Apr 03 13:10:54 2015 +0200 @@ -405,15 +405,15 @@ if (!install_importlib) return; + if (_PyTime_Init() < 0) + Py_FatalError("Py_Initialize: can't initialize time"); + import_init(interp, sysmod); /* initialize the faulthandler module */ if (_PyFaulthandler_Init()) Py_FatalError("Py_Initialize: can't initialize faulthandler"); - if (_PyTime_Init() < 0) - Py_FatalError("Py_Initialize: can't initialize time"); - if (initfsencoding(interp) < 0) Py_FatalError("Py_Initialize: unable to load the file system codec"); diff -r f80d5faa60ee -r d976683671ba Python/pytime.c --- a/Python/pytime.c Fri Apr 03 11:09:08 2015 +0200 +++ b/Python/pytime.c Fri Apr 03 13:10:54 2015 +0200 @@ -159,6 +159,19 @@ } _PyTime_t +_PyTime_FromSeconds(int seconds) +{ + _PyTime_t t; + /* ensure that integer overflow cannot happen, int type should have 32 + bits, whereas _PyTime_t type has at least 64 bits (SEC_TO_MS takes 30 + bits). */ + assert((seconds >= 0 && seconds <= _PyTime_MAX / SEC_TO_NS) + || (seconds < 0 && seconds >= _PyTime_MIN / SEC_TO_NS)); + t = (_PyTime_t)seconds * SEC_TO_NS; + return t; +} + +_PyTime_t _PyTime_FromNanoseconds(PY_LONG_LONG ns) { _PyTime_t t; @@ -657,5 +670,9 @@ /* ensure that the operating system provides a monotonic clock */ if (_PyTime_GetMonotonicClockWithInfo(&t, NULL) < 0) return -1; + + /* check that _PyTime_FromSeconds() cannot overflow */ + assert(INT_MAX <= _PyTime_MAX / SEC_TO_NS); + assert(INT_MIN >= _PyTime_MIN / SEC_TO_NS); return 0; }