Issue #20320: select.select() and select.kqueue.control() now round the timeout
aways from zero, instead of rounding towards zero. It should make test_asyncio more reliable, especially test_timeout_rounding() test.
This commit is contained in:
parent
23f628de4a
commit
3c1b379ebd
|
@ -53,10 +53,19 @@ do { \
|
||||||
(tv_end.tv_usec - tv_start.tv_usec) * 0.000001)
|
(tv_end.tv_usec - tv_start.tv_usec) * 0.000001)
|
||||||
|
|
||||||
#ifndef Py_LIMITED_API
|
#ifndef Py_LIMITED_API
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
/* Round towards zero. */
|
||||||
|
_PyTime_ROUND_DOWN=0,
|
||||||
|
/* Round away from zero. */
|
||||||
|
_PyTime_ROUND_UP
|
||||||
|
} _PyTime_round_t;
|
||||||
|
|
||||||
/* Convert a number of seconds, int or float, to time_t. */
|
/* Convert a number of seconds, int or float, to time_t. */
|
||||||
PyAPI_FUNC(int) _PyTime_ObjectToTime_t(
|
PyAPI_FUNC(int) _PyTime_ObjectToTime_t(
|
||||||
PyObject *obj,
|
PyObject *obj,
|
||||||
time_t *sec);
|
time_t *sec,
|
||||||
|
_PyTime_round_t);
|
||||||
|
|
||||||
/* Convert a time_t to a PyLong. */
|
/* Convert a time_t to a PyLong. */
|
||||||
PyAPI_FUNC(PyObject *) _PyLong_FromTime_t(
|
PyAPI_FUNC(PyObject *) _PyLong_FromTime_t(
|
||||||
|
@ -72,7 +81,8 @@ PyAPI_FUNC(time_t) _PyLong_AsTime_t(
|
||||||
PyAPI_FUNC(int) _PyTime_ObjectToTimeval(
|
PyAPI_FUNC(int) _PyTime_ObjectToTimeval(
|
||||||
PyObject *obj,
|
PyObject *obj,
|
||||||
time_t *sec,
|
time_t *sec,
|
||||||
long *usec);
|
long *usec,
|
||||||
|
_PyTime_round_t);
|
||||||
|
|
||||||
/* Convert a number of seconds, int or float, to a timespec structure.
|
/* Convert a number of seconds, int or float, to a timespec structure.
|
||||||
nsec is in the range [0; 999999999] and rounded towards zero.
|
nsec is in the range [0; 999999999] and rounded towards zero.
|
||||||
|
@ -80,7 +90,8 @@ PyAPI_FUNC(int) _PyTime_ObjectToTimeval(
|
||||||
PyAPI_FUNC(int) _PyTime_ObjectToTimespec(
|
PyAPI_FUNC(int) _PyTime_ObjectToTimespec(
|
||||||
PyObject *obj,
|
PyObject *obj,
|
||||||
time_t *sec,
|
time_t *sec,
|
||||||
long *nsec);
|
long *nsec,
|
||||||
|
_PyTime_round_t);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Dummy to force linking. */
|
/* Dummy to force linking. */
|
||||||
|
|
|
@ -14,6 +14,8 @@ except ImportError:
|
||||||
SIZEOF_INT = sysconfig.get_config_var('SIZEOF_INT') or 4
|
SIZEOF_INT = sysconfig.get_config_var('SIZEOF_INT') or 4
|
||||||
TIME_MAXYEAR = (1 << 8 * SIZEOF_INT - 1) - 1
|
TIME_MAXYEAR = (1 << 8 * SIZEOF_INT - 1) - 1
|
||||||
TIME_MINYEAR = -TIME_MAXYEAR - 1
|
TIME_MINYEAR = -TIME_MAXYEAR - 1
|
||||||
|
_PyTime_ROUND_DOWN = 0
|
||||||
|
_PyTime_ROUND_UP = 1
|
||||||
|
|
||||||
|
|
||||||
class TimeTestCase(unittest.TestCase):
|
class TimeTestCase(unittest.TestCase):
|
||||||
|
@ -585,58 +587,116 @@ class TestPytime(unittest.TestCase):
|
||||||
@support.cpython_only
|
@support.cpython_only
|
||||||
def test_time_t(self):
|
def test_time_t(self):
|
||||||
from _testcapi import pytime_object_to_time_t
|
from _testcapi import pytime_object_to_time_t
|
||||||
for obj, time_t in (
|
for obj, time_t, rnd in (
|
||||||
(0, 0),
|
# Round towards zero
|
||||||
(-1, -1),
|
(0, 0, _PyTime_ROUND_DOWN),
|
||||||
(-1.0, -1),
|
(-1, -1, _PyTime_ROUND_DOWN),
|
||||||
(-1.9, -1),
|
(-1.0, -1, _PyTime_ROUND_DOWN),
|
||||||
(1.0, 1),
|
(-1.9, -1, _PyTime_ROUND_DOWN),
|
||||||
(1.9, 1),
|
(1.0, 1, _PyTime_ROUND_DOWN),
|
||||||
|
(1.9, 1, _PyTime_ROUND_DOWN),
|
||||||
|
# Round away from zero
|
||||||
|
(0, 0, _PyTime_ROUND_UP),
|
||||||
|
(-1, -1, _PyTime_ROUND_UP),
|
||||||
|
(-1.0, -1, _PyTime_ROUND_UP),
|
||||||
|
(-1.9, -2, _PyTime_ROUND_UP),
|
||||||
|
(1.0, 1, _PyTime_ROUND_UP),
|
||||||
|
(1.9, 2, _PyTime_ROUND_UP),
|
||||||
):
|
):
|
||||||
self.assertEqual(pytime_object_to_time_t(obj), time_t)
|
self.assertEqual(pytime_object_to_time_t(obj, rnd), time_t)
|
||||||
|
|
||||||
|
rnd = _PyTime_ROUND_DOWN
|
||||||
for invalid in self.invalid_values:
|
for invalid in self.invalid_values:
|
||||||
self.assertRaises(OverflowError, pytime_object_to_time_t, invalid)
|
self.assertRaises(OverflowError,
|
||||||
|
pytime_object_to_time_t, invalid, rnd)
|
||||||
|
|
||||||
@support.cpython_only
|
@support.cpython_only
|
||||||
def test_timeval(self):
|
def test_timeval(self):
|
||||||
from _testcapi import pytime_object_to_timeval
|
from _testcapi import pytime_object_to_timeval
|
||||||
for obj, timeval in (
|
for obj, timeval, rnd in (
|
||||||
(0, (0, 0)),
|
# Round towards zero
|
||||||
(-1, (-1, 0)),
|
(0, (0, 0), _PyTime_ROUND_DOWN),
|
||||||
(-1.0, (-1, 0)),
|
(-1, (-1, 0), _PyTime_ROUND_DOWN),
|
||||||
(1e-6, (0, 1)),
|
(-1.0, (-1, 0), _PyTime_ROUND_DOWN),
|
||||||
(-1e-6, (-1, 999999)),
|
(1e-6, (0, 1), _PyTime_ROUND_DOWN),
|
||||||
(-1.2, (-2, 800000)),
|
(1e-7, (0, 0), _PyTime_ROUND_DOWN),
|
||||||
(1.1234560, (1, 123456)),
|
(-1e-6, (-1, 999999), _PyTime_ROUND_DOWN),
|
||||||
(1.1234569, (1, 123456)),
|
(-1e-7, (-1, 999999), _PyTime_ROUND_DOWN),
|
||||||
(-1.1234560, (-2, 876544)),
|
(-1.2, (-2, 800000), _PyTime_ROUND_DOWN),
|
||||||
(-1.1234561, (-2, 876543)),
|
(0.9999999, (0, 999999), _PyTime_ROUND_DOWN),
|
||||||
|
(0.0000041, (0, 4), _PyTime_ROUND_DOWN),
|
||||||
|
(1.1234560, (1, 123456), _PyTime_ROUND_DOWN),
|
||||||
|
(1.1234569, (1, 123456), _PyTime_ROUND_DOWN),
|
||||||
|
(-0.0000040, (-1, 999996), _PyTime_ROUND_DOWN),
|
||||||
|
(-0.0000041, (-1, 999995), _PyTime_ROUND_DOWN),
|
||||||
|
(-1.1234560, (-2, 876544), _PyTime_ROUND_DOWN),
|
||||||
|
(-1.1234561, (-2, 876543), _PyTime_ROUND_DOWN),
|
||||||
|
# Round away from zero
|
||||||
|
(0, (0, 0), _PyTime_ROUND_UP),
|
||||||
|
(-1, (-1, 0), _PyTime_ROUND_UP),
|
||||||
|
(-1.0, (-1, 0), _PyTime_ROUND_UP),
|
||||||
|
(1e-6, (0, 1), _PyTime_ROUND_UP),
|
||||||
|
(1e-7, (0, 1), _PyTime_ROUND_UP),
|
||||||
|
(-1e-6, (-1, 999999), _PyTime_ROUND_UP),
|
||||||
|
(-1e-7, (-1, 999999), _PyTime_ROUND_UP),
|
||||||
|
(-1.2, (-2, 800000), _PyTime_ROUND_UP),
|
||||||
|
(0.9999999, (1, 0), _PyTime_ROUND_UP),
|
||||||
|
(0.0000041, (0, 5), _PyTime_ROUND_UP),
|
||||||
|
(1.1234560, (1, 123457), _PyTime_ROUND_UP),
|
||||||
|
(1.1234569, (1, 123457), _PyTime_ROUND_UP),
|
||||||
|
(-0.0000040, (-1, 999996), _PyTime_ROUND_UP),
|
||||||
|
(-0.0000041, (-1, 999995), _PyTime_ROUND_UP),
|
||||||
|
(-1.1234560, (-2, 876544), _PyTime_ROUND_UP),
|
||||||
|
(-1.1234561, (-2, 876543), _PyTime_ROUND_UP),
|
||||||
):
|
):
|
||||||
self.assertEqual(pytime_object_to_timeval(obj), timeval)
|
with self.subTest(obj=obj, round=rnd, timeval=timeval):
|
||||||
|
self.assertEqual(pytime_object_to_timeval(obj, rnd), timeval)
|
||||||
|
|
||||||
|
rnd = _PyTime_ROUND_DOWN
|
||||||
for invalid in self.invalid_values:
|
for invalid in self.invalid_values:
|
||||||
self.assertRaises(OverflowError, pytime_object_to_timeval, invalid)
|
self.assertRaises(OverflowError,
|
||||||
|
pytime_object_to_timeval, invalid, rnd)
|
||||||
|
|
||||||
@support.cpython_only
|
@support.cpython_only
|
||||||
def test_timespec(self):
|
def test_timespec(self):
|
||||||
from _testcapi import pytime_object_to_timespec
|
from _testcapi import pytime_object_to_timespec
|
||||||
for obj, timespec in (
|
for obj, timespec, rnd in (
|
||||||
(0, (0, 0)),
|
# Round towards zero
|
||||||
(-1, (-1, 0)),
|
(0, (0, 0), _PyTime_ROUND_DOWN),
|
||||||
(-1.0, (-1, 0)),
|
(-1, (-1, 0), _PyTime_ROUND_DOWN),
|
||||||
(1e-9, (0, 1)),
|
(-1.0, (-1, 0), _PyTime_ROUND_DOWN),
|
||||||
(-1e-9, (-1, 999999999)),
|
(1e-9, (0, 1), _PyTime_ROUND_DOWN),
|
||||||
(-1.2, (-2, 800000000)),
|
(1e-10, (0, 0), _PyTime_ROUND_DOWN),
|
||||||
(1.1234567890, (1, 123456789)),
|
(-1e-9, (-1, 999999999), _PyTime_ROUND_DOWN),
|
||||||
(1.1234567899, (1, 123456789)),
|
(-1e-10, (-1, 999999999), _PyTime_ROUND_DOWN),
|
||||||
(-1.1234567890, (-2, 876543211)),
|
(-1.2, (-2, 800000000), _PyTime_ROUND_DOWN),
|
||||||
(-1.1234567891, (-2, 876543210)),
|
(0.9999999999, (0, 999999999), _PyTime_ROUND_DOWN),
|
||||||
|
(1.1234567890, (1, 123456789), _PyTime_ROUND_DOWN),
|
||||||
|
(1.1234567899, (1, 123456789), _PyTime_ROUND_DOWN),
|
||||||
|
(-1.1234567890, (-2, 876543211), _PyTime_ROUND_DOWN),
|
||||||
|
(-1.1234567891, (-2, 876543210), _PyTime_ROUND_DOWN),
|
||||||
|
# Round away from zero
|
||||||
|
(0, (0, 0), _PyTime_ROUND_UP),
|
||||||
|
(-1, (-1, 0), _PyTime_ROUND_UP),
|
||||||
|
(-1.0, (-1, 0), _PyTime_ROUND_UP),
|
||||||
|
(1e-9, (0, 1), _PyTime_ROUND_UP),
|
||||||
|
(1e-10, (0, 1), _PyTime_ROUND_UP),
|
||||||
|
(-1e-9, (-1, 999999999), _PyTime_ROUND_UP),
|
||||||
|
(-1e-10, (-1, 999999999), _PyTime_ROUND_UP),
|
||||||
|
(-1.2, (-2, 800000000), _PyTime_ROUND_UP),
|
||||||
|
(0.9999999999, (1, 0), _PyTime_ROUND_UP),
|
||||||
|
(1.1234567890, (1, 123456790), _PyTime_ROUND_UP),
|
||||||
|
(1.1234567899, (1, 123456790), _PyTime_ROUND_UP),
|
||||||
|
(-1.1234567890, (-2, 876543211), _PyTime_ROUND_UP),
|
||||||
|
(-1.1234567891, (-2, 876543210), _PyTime_ROUND_UP),
|
||||||
):
|
):
|
||||||
self.assertEqual(pytime_object_to_timespec(obj), timespec)
|
with self.subTest(obj=obj, round=rnd, timespec=timespec):
|
||||||
|
self.assertEqual(pytime_object_to_timespec(obj, rnd), timespec)
|
||||||
|
|
||||||
|
rnd = _PyTime_ROUND_DOWN
|
||||||
for invalid in self.invalid_values:
|
for invalid in self.invalid_values:
|
||||||
self.assertRaises(OverflowError, pytime_object_to_timespec, invalid)
|
self.assertRaises(OverflowError,
|
||||||
|
pytime_object_to_timespec, invalid, rnd)
|
||||||
|
|
||||||
@unittest.skipUnless(time._STRUCT_TM_ITEMS == 11, "needs tm_zone support")
|
@unittest.skipUnless(time._STRUCT_TM_ITEMS == 11, "needs tm_zone support")
|
||||||
def test_localtime_timezone(self):
|
def test_localtime_timezone(self):
|
||||||
|
|
|
@ -25,6 +25,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #20320: select.select() and select.kqueue.control() now round the
|
||||||
|
timeout aways from zero, instead of rounding towards zero.
|
||||||
|
|
||||||
- Issue #20616: Add a format() method to tracemalloc.Traceback.
|
- Issue #20616: Add a format() method to tracemalloc.Traceback.
|
||||||
|
|
||||||
- Issue #19744: the ensurepip installation step now just prints a warning to
|
- Issue #19744: the ensurepip installation step now just prints a warning to
|
||||||
|
|
|
@ -2459,7 +2459,7 @@ date_local_from_object(PyObject *cls, PyObject *obj)
|
||||||
struct tm *tm;
|
struct tm *tm;
|
||||||
time_t t;
|
time_t t;
|
||||||
|
|
||||||
if (_PyTime_ObjectToTime_t(obj, &t) == -1)
|
if (_PyTime_ObjectToTime_t(obj, &t, _PyTime_ROUND_DOWN) == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
tm = localtime(&t);
|
tm = localtime(&t);
|
||||||
|
@ -4127,7 +4127,7 @@ datetime_from_timestamp(PyObject *cls, TM_FUNC f, PyObject *timestamp,
|
||||||
time_t timet;
|
time_t timet;
|
||||||
long us;
|
long us;
|
||||||
|
|
||||||
if (_PyTime_ObjectToTimeval(timestamp, &timet, &us) == -1)
|
if (_PyTime_ObjectToTimeval(timestamp, &timet, &us, _PyTime_ROUND_DOWN) == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
return datetime_from_timet_and_us(cls, f, timet, (int)us, tzinfo);
|
return datetime_from_timet_and_us(cls, f, timet, (int)us, tzinfo);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2516,14 +2516,27 @@ run_in_subinterp(PyObject *self, PyObject *args)
|
||||||
return PyLong_FromLong(r);
|
return PyLong_FromLong(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
check_time_rounding(int round)
|
||||||
|
{
|
||||||
|
if (round != _PyTime_ROUND_DOWN && round != _PyTime_ROUND_UP) {
|
||||||
|
PyErr_SetString(PyExc_ValueError, "invalid rounding");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
test_pytime_object_to_time_t(PyObject *self, PyObject *args)
|
test_pytime_object_to_time_t(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
PyObject *obj;
|
PyObject *obj;
|
||||||
time_t sec;
|
time_t sec;
|
||||||
if (!PyArg_ParseTuple(args, "O:pytime_object_to_time_t", &obj))
|
int round;
|
||||||
|
if (!PyArg_ParseTuple(args, "Oi:pytime_object_to_time_t", &obj, &round))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (_PyTime_ObjectToTime_t(obj, &sec) == -1)
|
if (check_time_rounding(round) < 0)
|
||||||
|
return NULL;
|
||||||
|
if (_PyTime_ObjectToTime_t(obj, &sec, round) == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
return _PyLong_FromTime_t(sec);
|
return _PyLong_FromTime_t(sec);
|
||||||
}
|
}
|
||||||
|
@ -2534,9 +2547,12 @@ test_pytime_object_to_timeval(PyObject *self, PyObject *args)
|
||||||
PyObject *obj;
|
PyObject *obj;
|
||||||
time_t sec;
|
time_t sec;
|
||||||
long usec;
|
long usec;
|
||||||
if (!PyArg_ParseTuple(args, "O:pytime_object_to_timeval", &obj))
|
int round;
|
||||||
|
if (!PyArg_ParseTuple(args, "Oi:pytime_object_to_timeval", &obj, &round))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (_PyTime_ObjectToTimeval(obj, &sec, &usec) == -1)
|
if (check_time_rounding(round) < 0)
|
||||||
|
return NULL;
|
||||||
|
if (_PyTime_ObjectToTimeval(obj, &sec, &usec, round) == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
return Py_BuildValue("Nl", _PyLong_FromTime_t(sec), usec);
|
return Py_BuildValue("Nl", _PyLong_FromTime_t(sec), usec);
|
||||||
}
|
}
|
||||||
|
@ -2547,9 +2563,12 @@ test_pytime_object_to_timespec(PyObject *self, PyObject *args)
|
||||||
PyObject *obj;
|
PyObject *obj;
|
||||||
time_t sec;
|
time_t sec;
|
||||||
long nsec;
|
long nsec;
|
||||||
if (!PyArg_ParseTuple(args, "O:pytime_object_to_timespec", &obj))
|
int round;
|
||||||
|
if (!PyArg_ParseTuple(args, "Oi:pytime_object_to_timespec", &obj, &round))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (_PyTime_ObjectToTimespec(obj, &sec, &nsec) == -1)
|
if (check_time_rounding(round) < 0)
|
||||||
|
return NULL;
|
||||||
|
if (_PyTime_ObjectToTimespec(obj, &sec, &nsec, round) == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
return Py_BuildValue("Nl", _PyLong_FromTime_t(sec), nsec);
|
return Py_BuildValue("Nl", _PyLong_FromTime_t(sec), nsec);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4901,9 +4901,9 @@ posix_utime(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
}
|
}
|
||||||
utime.now = 0;
|
utime.now = 0;
|
||||||
if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
|
if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0),
|
||||||
&a_sec, &a_nsec) == -1 ||
|
&a_sec, &a_nsec, _PyTime_ROUND_DOWN) == -1 ||
|
||||||
_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
|
_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1),
|
||||||
&m_sec, &m_nsec) == -1) {
|
&m_sec, &m_nsec, _PyTime_ROUND_DOWN) == -1) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
utime.atime_s = a_sec;
|
utime.atime_s = a_sec;
|
||||||
|
|
|
@ -214,7 +214,8 @@ select_select(PyObject *self, PyObject *args)
|
||||||
else {
|
else {
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
time_t sec;
|
time_t sec;
|
||||||
if (_PyTime_ObjectToTimeval(tout, &sec, &tv.tv_usec) == -1)
|
if (_PyTime_ObjectToTimeval(tout, &sec, &tv.tv_usec,
|
||||||
|
_PyTime_ROUND_UP) == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
assert(sizeof(tv.tv_sec) == sizeof(long));
|
assert(sizeof(tv.tv_sec) == sizeof(long));
|
||||||
#if SIZEOF_TIME_T > SIZEOF_LONG
|
#if SIZEOF_TIME_T > SIZEOF_LONG
|
||||||
|
@ -229,7 +230,8 @@ select_select(PyObject *self, PyObject *args)
|
||||||
/* 64-bit OS X has struct timeval.tv_usec as an int (and thus still 4
|
/* 64-bit OS X has struct timeval.tv_usec as an int (and thus still 4
|
||||||
bytes as required), but no longer defined by a long. */
|
bytes as required), but no longer defined by a long. */
|
||||||
long tv_usec;
|
long tv_usec;
|
||||||
if (_PyTime_ObjectToTimeval(tout, &tv.tv_sec, &tv_usec) == -1)
|
if (_PyTime_ObjectToTimeval(tout, &tv.tv_sec, &tv_usec,
|
||||||
|
_PyTime_ROUND_UP) == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
tv.tv_usec = tv_usec;
|
tv.tv_usec = tv_usec;
|
||||||
#endif
|
#endif
|
||||||
|
@ -2037,8 +2039,8 @@ kqueue_queue_control(kqueue_queue_Object *self, PyObject *args)
|
||||||
ptimeoutspec = NULL;
|
ptimeoutspec = NULL;
|
||||||
}
|
}
|
||||||
else if (PyNumber_Check(otimeout)) {
|
else if (PyNumber_Check(otimeout)) {
|
||||||
if (_PyTime_ObjectToTimespec(otimeout,
|
if (_PyTime_ObjectToTimespec(otimeout, &timeout.tv_sec,
|
||||||
&timeout.tv_sec, &timeout.tv_nsec) == -1)
|
&timeout.tv_nsec, _PyTime_ROUND_UP) == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (timeout.tv_sec < 0) {
|
if (timeout.tv_sec < 0) {
|
||||||
|
|
|
@ -799,7 +799,8 @@ signal_sigtimedwait(PyObject *self, PyObject *args)
|
||||||
&signals, &timeout))
|
&signals, &timeout))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (_PyTime_ObjectToTimespec(timeout, &tv_sec, &tv_nsec) == -1)
|
if (_PyTime_ObjectToTimespec(timeout, &tv_sec, &tv_nsec,
|
||||||
|
_PyTime_ROUND_DOWN) == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
buf.tv_sec = tv_sec;
|
buf.tv_sec = tv_sec;
|
||||||
buf.tv_nsec = tv_nsec;
|
buf.tv_nsec = tv_nsec;
|
||||||
|
|
|
@ -193,7 +193,7 @@ time_clock_settime(PyObject *self, PyObject *args)
|
||||||
if (!PyArg_ParseTuple(args, "iO:clock_settime", &clk_id, &obj))
|
if (!PyArg_ParseTuple(args, "iO:clock_settime", &clk_id, &obj))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (_PyTime_ObjectToTimespec(obj, &tv_sec, &tv_nsec) == -1)
|
if (_PyTime_ObjectToTimespec(obj, &tv_sec, &tv_nsec, _PyTime_ROUND_DOWN) == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
tp.tv_sec = tv_sec;
|
tp.tv_sec = tv_sec;
|
||||||
tp.tv_nsec = tv_nsec;
|
tp.tv_nsec = tv_nsec;
|
||||||
|
@ -341,7 +341,7 @@ parse_time_t_args(PyObject *args, char *format, time_t *pwhen)
|
||||||
whent = time(NULL);
|
whent = time(NULL);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (_PyTime_ObjectToTime_t(ot, &whent) == -1)
|
if (_PyTime_ObjectToTime_t(ot, &whent, _PyTime_ROUND_DOWN) == -1)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*pwhen = whent;
|
*pwhen = whent;
|
||||||
|
|
|
@ -152,7 +152,7 @@ _PyLong_FromTime_t(time_t t)
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
|
_PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
|
||||||
double denominator)
|
double denominator, _PyTime_round_t round)
|
||||||
{
|
{
|
||||||
assert(denominator <= LONG_MAX);
|
assert(denominator <= LONG_MAX);
|
||||||
if (PyFloat_Check(obj)) {
|
if (PyFloat_Check(obj)) {
|
||||||
|
@ -167,6 +167,20 @@ _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
|
||||||
intpart -= 1.0;
|
intpart -= 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
floatpart *= denominator;
|
||||||
|
if (round == _PyTime_ROUND_UP) {
|
||||||
|
if (intpart >= 0) {
|
||||||
|
floatpart = ceil(floatpart);
|
||||||
|
if (floatpart >= denominator) {
|
||||||
|
floatpart = 0.0;
|
||||||
|
intpart += 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
floatpart = floor(floatpart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
*sec = (time_t)intpart;
|
*sec = (time_t)intpart;
|
||||||
err = intpart - (double)*sec;
|
err = intpart - (double)*sec;
|
||||||
if (err <= -1.0 || err >= 1.0) {
|
if (err <= -1.0 || err >= 1.0) {
|
||||||
|
@ -174,7 +188,6 @@ _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
floatpart *= denominator;
|
|
||||||
*numerator = (long)floatpart;
|
*numerator = (long)floatpart;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -188,12 +201,18 @@ _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyTime_ObjectToTime_t(PyObject *obj, time_t *sec)
|
_PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round)
|
||||||
{
|
{
|
||||||
if (PyFloat_Check(obj)) {
|
if (PyFloat_Check(obj)) {
|
||||||
double d, intpart, err;
|
double d, intpart, err;
|
||||||
|
|
||||||
d = PyFloat_AsDouble(obj);
|
d = PyFloat_AsDouble(obj);
|
||||||
|
if (round == _PyTime_ROUND_UP) {
|
||||||
|
if (d >= 0)
|
||||||
|
d = ceil(d);
|
||||||
|
else
|
||||||
|
d = floor(d);
|
||||||
|
}
|
||||||
(void)modf(d, &intpart);
|
(void)modf(d, &intpart);
|
||||||
|
|
||||||
*sec = (time_t)intpart;
|
*sec = (time_t)intpart;
|
||||||
|
@ -213,15 +232,17 @@ _PyTime_ObjectToTime_t(PyObject *obj, time_t *sec)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec)
|
_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec,
|
||||||
|
_PyTime_round_t round)
|
||||||
{
|
{
|
||||||
return _PyTime_ObjectToDenominator(obj, sec, nsec, 1e9);
|
return _PyTime_ObjectToDenominator(obj, sec, nsec, 1e9, round);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec)
|
_PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec,
|
||||||
|
_PyTime_round_t round)
|
||||||
{
|
{
|
||||||
return _PyTime_ObjectToDenominator(obj, sec, usec, 1e6);
|
return _PyTime_ObjectToDenominator(obj, sec, usec, 1e6, round);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
Loading…
Reference in New Issue