[Python-checkins] cpython: Issue #22117: Add a new _PyTime_FromSeconds() function

victor.stinner python-checkins at python.org
Fri Apr 3 13:36:57 CEST 2015


https://hg.python.org/cpython/rev/d976683671ba
changeset:   95408:d976683671ba
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Fri Apr 03 13:10:54 2015 +0200
summary:
  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).

files:
  Include/pytime.h          |   5 ++++-
  Lib/test/test_time.py     |   7 +++++++
  Modules/_testcapimodule.c |  13 +++++++++++++
  Modules/_threadmodule.c   |   2 +-
  Python/pylifecycle.c      |   6 +++---
  Python/pytime.c           |  17 +++++++++++++++++
  6 files changed, 45 insertions(+), 5 deletions(-)


diff --git a/Include/pytime.h b/Include/pytime.h
--- a/Include/pytime.h
+++ b/Include/pytime.h
@@ -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 --git a/Lib/test/test_time.py b/Lib/test/test_time.py
--- a/Lib/test/test_time.py
+++ b/Lib/test/test_time.py
@@ -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 --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -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 --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c
--- a/Modules/_threadmodule.c
+++ b/Modules/_threadmodule.c
@@ -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 --git a/Python/pylifecycle.c b/Python/pylifecycle.c
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -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 --git a/Python/pytime.c b/Python/pytime.c
--- a/Python/pytime.c
+++ b/Python/pytime.c
@@ -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;
 }

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list