]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Issue #22117: Add a new _PyTime_FromSeconds() function
authorVictor Stinner <victor.stinner@gmail.com>
Fri, 3 Apr 2015 11:10:54 +0000 (13:10 +0200)
committerVictor Stinner <victor.stinner@gmail.com>
Fri, 3 Apr 2015 11:10:54 +0000 (13:10 +0200)
Fix also _Py_InitializeEx_Private(): initialize time before initializing
import, import_init() uses the _PyTime API (for thread locks).

Include/pytime.h
Lib/test/test_time.py
Modules/_testcapimodule.c
Modules/_threadmodule.c
Python/pylifecycle.c
Python/pytime.c

index bf237c8655b167af3ad6b9acd9c01efd80c3794b..bf0dcd86577fda0a549f5a15d2a5a508e41d2069 100644 (file)
@@ -66,7 +66,10 @@ PyAPI_FUNC(int) _PyTime_ObjectToTimespec(
     _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.
index a9f6fd87edbe05271dab3dbd2fb8aea98325561d..0891834c154e29d0894124472d69daf8b12f7e91 100644 (file)
@@ -731,6 +731,13 @@ class TestPytime(unittest.TestCase):
 @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
 
index 7b4f239637815fe040129f202face5fdf9134a2b..d6eb6d4509a1e11c67f909ae68999ad86a63c352 100644 (file)
@@ -3382,6 +3382,18 @@ return_result_with_error(PyObject *self, PyObject *args)
     Py_RETURN_NONE;
 }
 
+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)
 {
@@ -3651,6 +3663,7 @@ static PyMethodDef TestMethods[] = {
         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},
index 323447f9daa384b3bf7f20f90919c8aba660225d..812c8a3b6a39216c713028a3b22ab94df35f0f3c 100644 (file)
@@ -101,7 +101,7 @@ lock_acquire_parse_args(PyObject *args, PyObject *kwds,
     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 ;
 
index 38543e05efa7469f71fc6b552f4e3def552ba5a6..bab3a2f38a8c90ee84534f0fbf993b96619573f7 100644 (file)
@@ -405,15 +405,15 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib)
     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");
 
index 491bbea61129c15c2d6ebe939ccc0726df253e3a..02a93749c7168b22ed0b65134615f834f6595c2a 100644 (file)
@@ -158,6 +158,19 @@ _PyTime_overflow(void)
                     "timestamp too large to convert to C _PyTime_t");
 }
 
+_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)
 {
@@ -657,5 +670,9 @@ _PyTime_Init(void)
     /* 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;
 }