Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 13019fd

Browse files
committed
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).
1 parent 21dfffa commit 13019fd

6 files changed

Lines changed: 45 additions & 5 deletions

File tree

Include/pytime.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,10 @@ PyAPI_FUNC(int) _PyTime_ObjectToTimespec(
6666
_PyTime_round_t);
6767

6868

69-
/* Create a timestamp from a number of nanoseconds (C long). */
69+
/* Create a timestamp from a number of seconds. */
70+
PyAPI_FUNC(_PyTime_t) _PyTime_FromSeconds(int ns);
71+
72+
/* Create a timestamp from a number of nanoseconds. */
7073
PyAPI_FUNC(_PyTime_t) _PyTime_FromNanoseconds(PY_LONG_LONG ns);
7174

7275
/* Convert a number of seconds (Python float or int) to a timetamp.

Lib/test/test_time.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,13 @@ def test_short_times(self):
731731
@unittest.skipUnless(_testcapi is not None,
732732
'need the _testcapi module')
733733
class TestPyTime_t(unittest.TestCase):
734+
def test_FromSeconds(self):
735+
from _testcapi import PyTime_FromSeconds
736+
for seconds in (0, 3, -456, _testcapi.INT_MAX, _testcapi.INT_MIN):
737+
with self.subTest(seconds=seconds):
738+
self.assertEqual(PyTime_FromSeconds(seconds),
739+
seconds * SEC_TO_NS)
740+
734741
def test_FromSecondsObject(self):
735742
from _testcapi import PyTime_FromSecondsObject
736743

Modules/_testcapimodule.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3382,6 +3382,18 @@ return_result_with_error(PyObject *self, PyObject *args)
33823382
Py_RETURN_NONE;
33833383
}
33843384

3385+
static PyObject *
3386+
test_pytime_fromseconds(PyObject *self, PyObject *args)
3387+
{
3388+
int seconds;
3389+
_PyTime_t ts;
3390+
3391+
if (!PyArg_ParseTuple(args, "i", &seconds))
3392+
return NULL;
3393+
ts = _PyTime_FromSeconds(seconds);
3394+
return _PyTime_AsNanosecondsObject(ts);
3395+
}
3396+
33853397
static PyObject *
33863398
test_pytime_fromsecondsobject(PyObject *self, PyObject *args)
33873399
{
@@ -3651,6 +3663,7 @@ static PyMethodDef TestMethods[] = {
36513663
return_null_without_error, METH_NOARGS},
36523664
{"return_result_with_error",
36533665
return_result_with_error, METH_NOARGS},
3666+
{"PyTime_FromSeconds", test_pytime_fromseconds, METH_VARARGS},
36543667
{"PyTime_FromSecondsObject", test_pytime_fromsecondsobject, METH_VARARGS},
36553668
{"PyTime_AsSecondsDouble", test_pytime_assecondsdouble, METH_VARARGS},
36563669
{"PyTime_AsTimeval", test_PyTime_AsTimeval, METH_VARARGS},

Modules/_threadmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ lock_acquire_parse_args(PyObject *args, PyObject *kwds,
101101
char *kwlist[] = {"blocking", "timeout", NULL};
102102
int blocking = 1;
103103
PyObject *timeout_obj = NULL;
104-
const _PyTime_t unset_timeout = _PyTime_FromNanoseconds(-1000000000);
104+
const _PyTime_t unset_timeout = _PyTime_FromSeconds(-1);
105105

106106
*timeout = unset_timeout ;
107107

Python/pylifecycle.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -405,15 +405,15 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib)
405405
if (!install_importlib)
406406
return;
407407

408+
if (_PyTime_Init() < 0)
409+
Py_FatalError("Py_Initialize: can't initialize time");
410+
408411
import_init(interp, sysmod);
409412

410413
/* initialize the faulthandler module */
411414
if (_PyFaulthandler_Init())
412415
Py_FatalError("Py_Initialize: can't initialize faulthandler");
413416

414-
if (_PyTime_Init() < 0)
415-
Py_FatalError("Py_Initialize: can't initialize time");
416-
417417
if (initfsencoding(interp) < 0)
418418
Py_FatalError("Py_Initialize: unable to load the file system codec");
419419

Python/pytime.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,19 @@ _PyTime_overflow(void)
158158
"timestamp too large to convert to C _PyTime_t");
159159
}
160160

161+
_PyTime_t
162+
_PyTime_FromSeconds(int seconds)
163+
{
164+
_PyTime_t t;
165+
/* ensure that integer overflow cannot happen, int type should have 32
166+
bits, whereas _PyTime_t type has at least 64 bits (SEC_TO_MS takes 30
167+
bits). */
168+
assert((seconds >= 0 && seconds <= _PyTime_MAX / SEC_TO_NS)
169+
|| (seconds < 0 && seconds >= _PyTime_MIN / SEC_TO_NS));
170+
t = (_PyTime_t)seconds * SEC_TO_NS;
171+
return t;
172+
}
173+
161174
_PyTime_t
162175
_PyTime_FromNanoseconds(PY_LONG_LONG ns)
163176
{
@@ -657,5 +670,9 @@ _PyTime_Init(void)
657670
/* ensure that the operating system provides a monotonic clock */
658671
if (_PyTime_GetMonotonicClockWithInfo(&t, NULL) < 0)
659672
return -1;
673+
674+
/* check that _PyTime_FromSeconds() cannot overflow */
675+
assert(INT_MAX <= _PyTime_MAX / SEC_TO_NS);
676+
assert(INT_MIN >= _PyTime_MIN / SEC_TO_NS);
660677
return 0;
661678
}

0 commit comments

Comments
 (0)