Issue #10278: Add an optional strict argument to time.steady(), False by default

This commit is contained in:
Victor Stinner 2012-03-15 01:17:09 +01:00
parent ec919cc74d
commit 071eca3f5c
3 changed files with 57 additions and 18 deletions

View File

@ -226,7 +226,7 @@ The module defines the following functions and data items:
The earliest date for which it can generate a time is platform-dependent.
.. function:: steady()
.. function:: steady(strict=False)
.. index::
single: benchmarking
@ -236,6 +236,11 @@ The module defines the following functions and data items:
adjusted. The reference point of the returned value is undefined so only the
difference of consecutive calls is valid.
If available, a monotonic clock is used. By default, if *strict* is False,
the function falls back to another clock if the monotonic clock failed or is
not available. If *strict* is True, raise an :exc:`OSError` on error or
:exc:`NotImplementedError` if no monotonic clock is available.
.. versionadded:: 3.3

View File

@ -340,6 +340,16 @@ class TimeTestCase(unittest.TestCase):
self.assertGreater(t2, t1)
self.assertAlmostEqual(dt, 0.1, delta=0.2)
def test_steady_strict(self):
try:
t1 = time.steady(strict=True)
except OSError as err:
self.skipTest("the monotonic clock failed: %s" % err)
except NotImplementedError:
self.skipTest("no monotonic clock available")
t2 = time.steady(strict=True)
self.assertGreaterEqual(t2, t1)
def test_localtime_failure(self):
# Issue #13847: check for localtime() failure
invalid_time_t = None

View File

@ -45,18 +45,12 @@
/* Forward declarations */
static int floatsleep(double);
static double floattime(void);
static PyObject* floattime(void);
static PyObject *
time_time(PyObject *self, PyObject *unused)
{
double secs;
secs = floattime();
if (secs == 0.0) {
PyErr_SetFromErrno(PyExc_IOError);
return NULL;
}
return PyFloat_FromDouble(secs);
return floattime();
}
PyDoc_STRVAR(time_doc,
@ -768,11 +762,11 @@ the local timezone used by methods such as localtime, but this behaviour\n\
should not be relied on.");
#endif /* HAVE_WORKING_TZSET */
static PyObject *
time_steady(PyObject *self, PyObject *unused)
static PyObject*
steady_clock(int strict)
{
#if defined(MS_WINDOWS) && !defined(__BORLANDC__)
return win32_clock(1);
return win32_clock(!strict);
#elif defined(__APPLE__)
uint64_t time = mach_absolute_time();
double secs;
@ -806,14 +800,37 @@ time_steady(PyObject *self, PyObject *unused)
if (Py_ARRAY_LENGTH(clk_ids) <= clk_index)
clk_index = -1;
}
return time_time(self, NULL);
if (strict) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
return floattime();
#else
return time_time(self, NULL);
if (strict) {
PyErr_SetString(PyExc_NotImplementedError,
"no steady clock available on your platform");
return NULL;
}
return floattime();
#endif
}
static PyObject *
time_steady(PyObject *self, PyObject *args, PyObject *kwargs)
{
static char *kwlist[] = {"strict", NULL};
int strict = 0;
if (!PyArg_ParseTupleAndKeywords(
args, kwargs, "|i:steady", kwlist,
&strict))
return NULL;
return steady_clock(strict);
}
PyDoc_STRVAR(steady_doc,
"steady() -> float\n\
"steady(strict=False) -> float\n\
\n\
Return the current time as a floating point number expressed in seconds.\n\
This clock advances at a steady rate relative to real time and it may not\n\
@ -949,7 +966,8 @@ static PyMethodDef time_methods[] = {
#ifdef HAVE_MKTIME
{"mktime", time_mktime, METH_O, mktime_doc},
#endif
{"steady", time_steady, METH_NOARGS, steady_doc},
{"steady", (PyCFunction)time_steady, METH_VARARGS|METH_KEYWORDS,
steady_doc},
#ifdef HAVE_STRFTIME
{"strftime", time_strftime, METH_VARARGS, strftime_doc},
#endif
@ -1041,12 +1059,18 @@ PyInit_time(void)
return m;
}
static double
static PyObject*
floattime(void)
{
_PyTime_timeval t;
double secs;
_PyTime_gettimeofday(&t);
return (double)t.tv_sec + t.tv_usec*0.000001;
secs = (double)t.tv_sec + t.tv_usec*0.000001;
if (secs == 0.0) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
return PyFloat_FromDouble(secs);
}