mirror of
https://github.com/python/cpython.git
synced 2026-01-06 15:32:22 +00:00
gh-67795: Accept any real numbers as timestamp and timeout (GH-139224)
Functions that take timestamp or timeout arguments now accept any real numbers (such as Decimal and Fraction), not only integers or floats, although this does not improve precision.
This commit is contained in:
parent
6ec058a1f7
commit
1a2e00c97a
20 changed files with 342 additions and 97 deletions
|
|
@ -368,8 +368,20 @@ pytime_object_to_denominator(PyObject *obj, time_t *sec, long *numerator,
|
|||
{
|
||||
assert(denominator >= 1);
|
||||
|
||||
if (PyFloat_Check(obj)) {
|
||||
if (PyIndex_Check(obj)) {
|
||||
*sec = _PyLong_AsTime_t(obj);
|
||||
*numerator = 0;
|
||||
if (*sec == (time_t)-1 && PyErr_Occurred()) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
double d = PyFloat_AsDouble(obj);
|
||||
if (d == -1 && PyErr_Occurred()) {
|
||||
*numerator = 0;
|
||||
return -1;
|
||||
}
|
||||
if (isnan(d)) {
|
||||
*numerator = 0;
|
||||
PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)");
|
||||
|
|
@ -378,30 +390,28 @@ pytime_object_to_denominator(PyObject *obj, time_t *sec, long *numerator,
|
|||
return pytime_double_to_denominator(d, sec, numerator,
|
||||
denominator, round);
|
||||
}
|
||||
else {
|
||||
*sec = _PyLong_AsTime_t(obj);
|
||||
*numerator = 0;
|
||||
if (*sec == (time_t)-1 && PyErr_Occurred()) {
|
||||
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"argument must be int or float, not %T", obj);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
_PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round)
|
||||
{
|
||||
if (PyFloat_Check(obj)) {
|
||||
if (PyIndex_Check(obj)) {
|
||||
*sec = _PyLong_AsTime_t(obj);
|
||||
if (*sec == (time_t)-1 && PyErr_Occurred()) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
double intpart;
|
||||
/* volatile avoids optimization changing how numbers are rounded */
|
||||
volatile double d;
|
||||
|
||||
d = PyFloat_AsDouble(obj);
|
||||
if (d == -1 && PyErr_Occurred()) {
|
||||
return -1;
|
||||
}
|
||||
if (isnan(d)) {
|
||||
PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)");
|
||||
return -1;
|
||||
|
|
@ -418,13 +428,6 @@ _PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round)
|
|||
*sec = (time_t)intpart;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
*sec = _PyLong_AsTime_t(obj);
|
||||
if (*sec == (time_t)-1 && PyErr_Occurred()) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -586,39 +589,38 @@ static int
|
|||
pytime_from_object(PyTime_t *tp, PyObject *obj, _PyTime_round_t round,
|
||||
long unit_to_ns)
|
||||
{
|
||||
if (PyFloat_Check(obj)) {
|
||||
if (PyIndex_Check(obj)) {
|
||||
long long sec = PyLong_AsLongLong(obj);
|
||||
if (sec == -1 && PyErr_Occurred()) {
|
||||
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
|
||||
pytime_overflow();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static_assert(sizeof(long long) <= sizeof(PyTime_t),
|
||||
"PyTime_t is smaller than long long");
|
||||
PyTime_t ns = (PyTime_t)sec;
|
||||
if (pytime_mul(&ns, unit_to_ns) < 0) {
|
||||
pytime_overflow();
|
||||
return -1;
|
||||
}
|
||||
|
||||
*tp = ns;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
double d;
|
||||
d = PyFloat_AsDouble(obj);
|
||||
if (d == -1 && PyErr_Occurred()) {
|
||||
return -1;
|
||||
}
|
||||
if (isnan(d)) {
|
||||
PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)");
|
||||
return -1;
|
||||
}
|
||||
return pytime_from_double(tp, d, round, unit_to_ns);
|
||||
}
|
||||
|
||||
long long sec = PyLong_AsLongLong(obj);
|
||||
if (sec == -1 && PyErr_Occurred()) {
|
||||
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
|
||||
pytime_overflow();
|
||||
}
|
||||
else if (PyErr_ExceptionMatches(PyExc_TypeError)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"'%T' object cannot be interpreted as an integer or float",
|
||||
obj);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static_assert(sizeof(long long) <= sizeof(PyTime_t),
|
||||
"PyTime_t is smaller than long long");
|
||||
PyTime_t ns = (PyTime_t)sec;
|
||||
if (pytime_mul(&ns, unit_to_ns) < 0) {
|
||||
pytime_overflow();
|
||||
return -1;
|
||||
}
|
||||
|
||||
*tp = ns;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue