Commit 071eca3f authored by Victor Stinner's avatar Victor Stinner

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

parent ec919cc7
...@@ -226,7 +226,7 @@ The module defines the following functions and data items: ...@@ -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. The earliest date for which it can generate a time is platform-dependent.
.. function:: steady() .. function:: steady(strict=False)
.. index:: .. index::
single: benchmarking single: benchmarking
...@@ -236,6 +236,11 @@ The module defines the following functions and data items: ...@@ -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 adjusted. The reference point of the returned value is undefined so only the
difference of consecutive calls is valid. 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 .. versionadded:: 3.3
......
...@@ -340,6 +340,16 @@ class TimeTestCase(unittest.TestCase): ...@@ -340,6 +340,16 @@ class TimeTestCase(unittest.TestCase):
self.assertGreater(t2, t1) self.assertGreater(t2, t1)
self.assertAlmostEqual(dt, 0.1, delta=0.2) 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): def test_localtime_failure(self):
# Issue #13847: check for localtime() failure # Issue #13847: check for localtime() failure
invalid_time_t = None invalid_time_t = None
......
...@@ -45,18 +45,12 @@ ...@@ -45,18 +45,12 @@
/* Forward declarations */ /* Forward declarations */
static int floatsleep(double); static int floatsleep(double);
static double floattime(void); static PyObject* floattime(void);
static PyObject * static PyObject *
time_time(PyObject *self, PyObject *unused) time_time(PyObject *self, PyObject *unused)
{ {
double secs; return floattime();
secs = floattime();
if (secs == 0.0) {
PyErr_SetFromErrno(PyExc_IOError);
return NULL;
}
return PyFloat_FromDouble(secs);
} }
PyDoc_STRVAR(time_doc, PyDoc_STRVAR(time_doc,
...@@ -768,11 +762,11 @@ the local timezone used by methods such as localtime, but this behaviour\n\ ...@@ -768,11 +762,11 @@ the local timezone used by methods such as localtime, but this behaviour\n\
should not be relied on."); should not be relied on.");
#endif /* HAVE_WORKING_TZSET */ #endif /* HAVE_WORKING_TZSET */
static PyObject * static PyObject*
time_steady(PyObject *self, PyObject *unused) steady_clock(int strict)
{ {
#if defined(MS_WINDOWS) && !defined(__BORLANDC__) #if defined(MS_WINDOWS) && !defined(__BORLANDC__)
return win32_clock(1); return win32_clock(!strict);
#elif defined(__APPLE__) #elif defined(__APPLE__)
uint64_t time = mach_absolute_time(); uint64_t time = mach_absolute_time();
double secs; double secs;
...@@ -806,14 +800,37 @@ time_steady(PyObject *self, PyObject *unused) ...@@ -806,14 +800,37 @@ time_steady(PyObject *self, PyObject *unused)
if (Py_ARRAY_LENGTH(clk_ids) <= clk_index) if (Py_ARRAY_LENGTH(clk_ids) <= clk_index)
clk_index = -1; clk_index = -1;
} }
return time_time(self, NULL); if (strict) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
return floattime();
#else #else
return time_time(self, NULL); if (strict) {
PyErr_SetString(PyExc_NotImplementedError,
"no steady clock available on your platform");
return NULL;
}
return floattime();
#endif #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, PyDoc_STRVAR(steady_doc,
"steady() -> float\n\ "steady(strict=False) -> float\n\
\n\ \n\
Return the current time as a floating point number expressed in seconds.\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\ This clock advances at a steady rate relative to real time and it may not\n\
...@@ -949,7 +966,8 @@ static PyMethodDef time_methods[] = { ...@@ -949,7 +966,8 @@ static PyMethodDef time_methods[] = {
#ifdef HAVE_MKTIME #ifdef HAVE_MKTIME
{"mktime", time_mktime, METH_O, mktime_doc}, {"mktime", time_mktime, METH_O, mktime_doc},
#endif #endif
{"steady", time_steady, METH_NOARGS, steady_doc}, {"steady", (PyCFunction)time_steady, METH_VARARGS|METH_KEYWORDS,
steady_doc},
#ifdef HAVE_STRFTIME #ifdef HAVE_STRFTIME
{"strftime", time_strftime, METH_VARARGS, strftime_doc}, {"strftime", time_strftime, METH_VARARGS, strftime_doc},
#endif #endif
...@@ -1041,12 +1059,18 @@ PyInit_time(void) ...@@ -1041,12 +1059,18 @@ PyInit_time(void)
return m; return m;
} }
static double static PyObject*
floattime(void) floattime(void)
{ {
_PyTime_timeval t; _PyTime_timeval t;
double secs;
_PyTime_gettimeofday(&t); _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);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment