mirror of
https://github.com/python/cpython.git
synced 2025-09-02 23:18:25 +00:00
Issue #13847: time.localtime() and time.gmtime() now raise an OSError instead
of ValueError on failure. time.ctime() and time.asctime() now raises an OSError if localtime() failed.
This commit is contained in:
parent
c9e7ef7d70
commit
c1b5d34ede
3 changed files with 81 additions and 52 deletions
|
@ -343,6 +343,21 @@ class TimeTestCase(unittest.TestCase):
|
||||||
dt = t2 - t1
|
dt = t2 - t1
|
||||||
self.assertAlmostEqual(dt, 0.1, delta=0.2)
|
self.assertAlmostEqual(dt, 0.1, delta=0.2)
|
||||||
|
|
||||||
|
def test_localtime_failure(self):
|
||||||
|
# Issue #13847: check for localtime() failure
|
||||||
|
invalid_time_t = 2**60
|
||||||
|
try:
|
||||||
|
time.localtime(invalid_time_t)
|
||||||
|
except ValueError as err:
|
||||||
|
if str(err) == "timestamp out of range for platform time_t":
|
||||||
|
self.skipTest("need 64-bit time_t")
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
self.assertRaises(OSError, time.localtime, invalid_time_t)
|
||||||
|
self.assertRaises(OSError, time.gmtime, invalid_time_t)
|
||||||
|
self.assertRaises(OSError, time.ctime, invalid_time_t)
|
||||||
|
|
||||||
class TestLocale(unittest.TestCase):
|
class TestLocale(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|
|
@ -461,6 +461,10 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #13847: time.localtime() and time.gmtime() now raise an OSError instead
|
||||||
|
of ValueError on failure. time.ctime() and time.asctime() now raises an
|
||||||
|
OSError if localtime() failed.
|
||||||
|
|
||||||
- Issue #13862: Fix spurious failure in test_zlib due to runtime/compile time
|
- Issue #13862: Fix spurious failure in test_zlib due to runtime/compile time
|
||||||
minor versions not matching.
|
minor versions not matching.
|
||||||
|
|
||||||
|
|
|
@ -247,55 +247,53 @@ tmtotuple(struct tm *p)
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
time_convert(double when, struct tm * (*function)(const time_t *))
|
|
||||||
{
|
|
||||||
struct tm *p;
|
|
||||||
time_t whent = _PyTime_DoubleToTimet(when);
|
|
||||||
|
|
||||||
if (whent == (time_t)-1 && PyErr_Occurred())
|
|
||||||
return NULL;
|
|
||||||
errno = 0;
|
|
||||||
p = function(&whent);
|
|
||||||
if (p == NULL) {
|
|
||||||
#ifdef EINVAL
|
|
||||||
if (errno == 0)
|
|
||||||
errno = EINVAL;
|
|
||||||
#endif
|
|
||||||
return PyErr_SetFromErrno(PyExc_ValueError);
|
|
||||||
}
|
|
||||||
return tmtotuple(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parse arg tuple that can contain an optional float-or-None value;
|
/* Parse arg tuple that can contain an optional float-or-None value;
|
||||||
format needs to be "|O:name".
|
format needs to be "|O:name".
|
||||||
Returns non-zero on success (parallels PyArg_ParseTuple).
|
Returns non-zero on success (parallels PyArg_ParseTuple).
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
parse_time_double_args(PyObject *args, char *format, double *pwhen)
|
parse_time_t_args(PyObject *args, char *format, time_t *pwhen)
|
||||||
{
|
{
|
||||||
PyObject *ot = NULL;
|
PyObject *ot = NULL;
|
||||||
|
time_t whent;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, format, &ot))
|
if (!PyArg_ParseTuple(args, format, &ot))
|
||||||
return 0;
|
return 0;
|
||||||
if (ot == NULL || ot == Py_None)
|
if (ot == NULL || ot == Py_None) {
|
||||||
*pwhen = floattime();
|
whent = time(NULL);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
double when = PyFloat_AsDouble(ot);
|
double d = PyFloat_AsDouble(ot);
|
||||||
if (PyErr_Occurred())
|
if (PyErr_Occurred())
|
||||||
return 0;
|
return 0;
|
||||||
*pwhen = when;
|
whent = _PyTime_DoubleToTimet(d);
|
||||||
|
if (whent == (time_t)-1 && PyErr_Occurred())
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
*pwhen = whent;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
time_gmtime(PyObject *self, PyObject *args)
|
time_gmtime(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
double when;
|
time_t when;
|
||||||
if (!parse_time_double_args(args, "|O:gmtime", &when))
|
struct tm buf, *local;
|
||||||
|
|
||||||
|
if (!parse_time_t_args(args, "|O:gmtime", &when))
|
||||||
return NULL;
|
return NULL;
|
||||||
return time_convert(when, gmtime);
|
|
||||||
|
errno = 0;
|
||||||
|
local = gmtime(&when);
|
||||||
|
if (local == NULL) {
|
||||||
|
#ifdef EINVAL
|
||||||
|
if (errno == 0)
|
||||||
|
errno = EINVAL;
|
||||||
|
#endif
|
||||||
|
return PyErr_SetFromErrno(PyExc_OSError);
|
||||||
|
}
|
||||||
|
buf = *local;
|
||||||
|
return tmtotuple(&buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(gmtime_doc,
|
PyDoc_STRVAR(gmtime_doc,
|
||||||
|
@ -305,13 +303,37 @@ PyDoc_STRVAR(gmtime_doc,
|
||||||
Convert seconds since the Epoch to a time tuple expressing UTC (a.k.a.\n\
|
Convert seconds since the Epoch to a time tuple expressing UTC (a.k.a.\n\
|
||||||
GMT). When 'seconds' is not passed in, convert the current time instead.");
|
GMT). When 'seconds' is not passed in, convert the current time instead.");
|
||||||
|
|
||||||
|
static int
|
||||||
|
pylocaltime(time_t *timep, struct tm *result)
|
||||||
|
{
|
||||||
|
struct tm *local;
|
||||||
|
|
||||||
|
assert (timep != NULL);
|
||||||
|
local = localtime(timep);
|
||||||
|
if (local == NULL) {
|
||||||
|
/* unconvertible time */
|
||||||
|
#ifdef EINVAL
|
||||||
|
if (errno == 0)
|
||||||
|
errno = EINVAL;
|
||||||
|
#endif
|
||||||
|
PyErr_SetFromErrno(PyExc_OSError);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*result = *local;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
time_localtime(PyObject *self, PyObject *args)
|
time_localtime(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
double when;
|
time_t when;
|
||||||
if (!parse_time_double_args(args, "|O:localtime", &when))
|
struct tm buf;
|
||||||
|
|
||||||
|
if (!parse_time_t_args(args, "|O:localtime", &when))
|
||||||
return NULL;
|
return NULL;
|
||||||
return time_convert(when, localtime);
|
if (pylocaltime(&when, &buf) == 1)
|
||||||
|
return NULL;
|
||||||
|
return tmtotuple(&buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(localtime_doc,
|
PyDoc_STRVAR(localtime_doc,
|
||||||
|
@ -462,7 +484,8 @@ time_strftime(PyObject *self, PyObject *args)
|
||||||
|
|
||||||
if (tup == NULL) {
|
if (tup == NULL) {
|
||||||
time_t tt = time(NULL);
|
time_t tt = time(NULL);
|
||||||
buf = *localtime(&tt);
|
if (pylocaltime(&tt, &buf) == -1)
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
else if (!gettmarg(tup, &buf) || !checktm(&buf))
|
else if (!gettmarg(tup, &buf) || !checktm(&buf))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -627,7 +650,9 @@ time_asctime(PyObject *self, PyObject *args)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (tup == NULL) {
|
if (tup == NULL) {
|
||||||
time_t tt = time(NULL);
|
time_t tt = time(NULL);
|
||||||
buf = *localtime(&tt);
|
if (pylocaltime(&tt, &buf) == -1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
} else if (!gettmarg(tup, &buf) || !checktm(&buf))
|
} else if (!gettmarg(tup, &buf) || !checktm(&buf))
|
||||||
return NULL;
|
return NULL;
|
||||||
return _asctime(&buf);
|
return _asctime(&buf);
|
||||||
|
@ -643,28 +668,13 @@ is used.");
|
||||||
static PyObject *
|
static PyObject *
|
||||||
time_ctime(PyObject *self, PyObject *args)
|
time_ctime(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
PyObject *ot = NULL;
|
|
||||||
time_t tt;
|
time_t tt;
|
||||||
struct tm *timeptr;
|
struct tm buf;
|
||||||
|
if (!parse_time_t_args(args, "|O:ctime", &tt))
|
||||||
if (!PyArg_UnpackTuple(args, "ctime", 0, 1, &ot))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
if (ot == NULL || ot == Py_None)
|
if (pylocaltime(&tt, &buf) == -1)
|
||||||
tt = time(NULL);
|
|
||||||
else {
|
|
||||||
double dt = PyFloat_AsDouble(ot);
|
|
||||||
if (PyErr_Occurred())
|
|
||||||
return NULL;
|
|
||||||
tt = _PyTime_DoubleToTimet(dt);
|
|
||||||
if (tt == (time_t)-1 && PyErr_Occurred())
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
timeptr = localtime(&tt);
|
|
||||||
if (timeptr == NULL) {
|
|
||||||
PyErr_SetString(PyExc_ValueError, "unconvertible time");
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
return _asctime(&buf);
|
||||||
return _asctime(timeptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(ctime_doc,
|
PyDoc_STRVAR(ctime_doc,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue