Python-checkins
Threads by month
- ----- 2025 -----
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
November 2017
- 3 participants
- 427 discussions
https://github.com/python/cpython/commit/0d2c645d41eee4ec7549c86ccc23970b69…
commit: 0d2c645d41eee4ec7549c86ccc23970b692a48b0
branch: master
author: Christian Heimes <christian(a)python.org>
committer: GitHub <noreply(a)github.com>
date: 2017-11-02T17:38:11+01:00
summary:
Update multissltests: 1.0.2m, 1.1.0g (#4232)
files:
M Tools/ssl/multissltests.py
diff --git a/Tools/ssl/multissltests.py b/Tools/ssl/multissltests.py
index 994e420818e..ce5bbd85308 100755
--- a/Tools/ssl/multissltests.py
+++ b/Tools/ssl/multissltests.py
@@ -41,15 +41,14 @@
log = logging.getLogger("multissl")
OPENSSL_OLD_VERSIONS = [
- "0.9.8zc",
"0.9.8zh",
"1.0.1u",
]
OPENSSL_RECENT_VERSIONS = [
"1.0.2",
- "1.0.2l",
- "1.1.0f",
+ "1.0.2m",
+ "1.1.0g",
]
LIBRESSL_OLD_VERSIONS = [
1
0
Returning 1 from the set_progress_handler handler cancels query (GH-4120)
by Berker Peksag Nov. 2, 2017
by Berker Peksag Nov. 2, 2017
Nov. 2, 2017
https://github.com/python/cpython/commit/ac03c03b305273f39d5374e2826526d4ab…
commit: ac03c03b305273f39d5374e2826526d4ab6bb415
branch: master
author: Simon Willison <simonw(a)eventbrite.com>
committer: Berker Peksag <berker.peksag(a)gmail.com>
date: 2017-11-02T17:34:11+03:00
summary:
Returning 1 from the set_progress_handler handler cancels query (GH-4120)
files:
M Doc/library/sqlite3.rst
diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst
index 9fef7d7f03f..ef0c0bf64cd 100644
--- a/Doc/library/sqlite3.rst
+++ b/Doc/library/sqlite3.rst
@@ -421,6 +421,10 @@ Connection Objects
If you want to clear any previously installed progress handler, call the
method with :const:`None` for *handler*.
+ Returning a non-zero value from the handler function will terminate the
+ currently executing query and cause it to raise an :exc:`OperationalError`
+ exception.
+
.. method:: set_trace_callback(trace_callback)
1
0
Nov. 2, 2017
https://github.com/python/cpython/commit/c29b585fd4b5a91d17fc5dd41d86edff28…
commit: c29b585fd4b5a91d17fc5dd41d86edff28a30da3
branch: master
author: Victor Stinner <victor.stinner(a)gmail.com>
committer: GitHub <noreply(a)github.com>
date: 2017-11-02T07:28:27-07:00
summary:
bpo-31784: Implement PEP 564: add time.time_ns() (#3989)
Add new time functions:
* time.clock_gettime_ns()
* time.clock_settime_ns()
* time.monotonic_ns()
* time.perf_counter_ns()
* time.process_time_ns()
* time.time_ns()
Add new _PyTime functions:
* _PyTime_FromTimespec()
* _PyTime_FromNanosecondsObject()
* _PyTime_FromTimeval()
Other changes:
* Add also os.times() tests to test_os.
* pytime_fromtimeval() and pytime_fromtimeval() now return
_PyTime_MAX or _PyTime_MIN on overflow, rather than undefined
behaviour
* _PyTime_FromNanoseconds() parameter type changes from long long to
_PyTime_t
files:
A Misc/NEWS.d/next/Library/2017-10-13-23-35-47.bpo-31784.6e57bd.rst
M Doc/library/time.rst
M Doc/whatsnew/3.7.rst
M Include/pytime.h
M Lib/test/test_os.py
M Lib/test/test_time.py
M Modules/_testcapimodule.c
M Modules/timemodule.c
M Python/pytime.c
diff --git a/Doc/library/time.rst b/Doc/library/time.rst
index 253df733bf3..4ffb4d22cd7 100644
--- a/Doc/library/time.rst
+++ b/Doc/library/time.rst
@@ -185,7 +185,7 @@ Functions
.. versionadded:: 3.3
-.. function:: clock_gettime(clk_id)
+.. function:: clock_gettime(clk_id) -> float
Return the time of the specified clock *clk_id*. Refer to
:ref:`time-clock-id-constants` for a list of accepted values for *clk_id*.
@@ -195,7 +195,16 @@ Functions
.. versionadded:: 3.3
-.. function:: clock_settime(clk_id, time)
+.. function:: clock_gettime_ns(clk_id) -> int
+
+ Similar to :func:`clock_gettime` but return time as nanoseconds.
+
+ Availability: Unix.
+
+ .. versionadded:: 3.7
+
+
+.. function:: clock_settime(clk_id, time: float)
Set the time of the specified clock *clk_id*. Currently,
:data:`CLOCK_REALTIME` is the only accepted value for *clk_id*.
@@ -205,6 +214,15 @@ Functions
.. versionadded:: 3.3
+.. function:: clock_settime_ns(clk_id, time: int)
+
+ Similar to :func:`clock_settime` but set time with nanoseconds.
+
+ Availability: Unix.
+
+ .. versionadded:: 3.7
+
+
.. function:: ctime([secs])
Convert a time expressed in seconds since the epoch to a string representing
@@ -267,7 +285,7 @@ Functions
The earliest date for which it can generate a time is platform-dependent.
-.. function:: monotonic()
+.. function:: monotonic() -> float
Return the value (in fractional seconds) of a monotonic clock, i.e. a clock
that cannot go backwards. The clock is not affected by system clock updates.
@@ -287,7 +305,13 @@ Functions
The function is now always available.
-.. function:: perf_counter()
+.. function:: monotonic_ns() -> int
+
+ Similar to :func:`monotonic`, but return time as nanoseconds.
+
+ .. versionadded:: 3.7
+
+.. function:: perf_counter() -> float
.. index::
single: benchmarking
@@ -300,8 +324,14 @@ Functions
.. versionadded:: 3.3
+.. function:: perf_counter_ns() -> int
+
+ Similar to :func:`perf_counter`, but return time as nanoseconds.
+
+ .. versionadded:: 3.7
-.. function:: process_time()
+
+.. function:: process_time() -> float
.. index::
single: CPU time
@@ -316,6 +346,12 @@ Functions
.. versionadded:: 3.3
+.. function:: process_time_ns() -> int
+
+ Similar to :func:`process_time` but return time as nanoseconds.
+
+ .. versionadded:: 3.7
+
.. function:: sleep(secs)
Suspend execution of the calling thread for the given number of seconds.
@@ -541,7 +577,7 @@ Functions
:class:`struct_time`, or having elements of the wrong type, a
:exc:`TypeError` is raised.
-.. function:: time()
+.. function:: time() -> float
Return the time in seconds since the epoch_ as a floating point
number. The specific date of the epoch and the handling of
@@ -567,6 +603,13 @@ Functions
of the calendar date may be accessed as attributes.
+.. function:: time_ns() -> int
+
+ Similar to :func:`time` but returns time as an integer number of nanoseconds
+ since the epoch_.
+
+ .. versionadded:: 3.7
+
.. function:: tzset()
Reset the time conversion rules used by the library routines. The environment
diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst
index d5836d509be..eb64c6a2b64 100644
--- a/Doc/whatsnew/3.7.rst
+++ b/Doc/whatsnew/3.7.rst
@@ -159,6 +159,32 @@ effort will be made to add such support.
PEP written by Erik M. Bray; implementation by Masayuki Yamamoto.
+PEP 564: Add new time functions with nanosecond resolution
+----------------------------------------------------------
+
+Add six new "nanosecond" variants of existing functions to the :mod:`time`
+module:
+
+* :func:`time.clock_gettime_ns`
+* :func:`time.clock_settime_ns`
+* :func:`time.monotonic_ns`
+* :func:`time.perf_counter_ns`
+* :func:`time.process_time_ns`
+* :func:`time.time_ns`
+
+While similar to the existing functions without the ``_ns`` suffix, they
+provide nanosecond resolution: they return a number of nanoseconds as a Python
+``int``.
+
+The ``time.time_ns()`` resolution is 3 times better than the ``time.time()``
+resolution on Linux and Windows.
+
+.. seealso::
+
+ :pep:`564` -- Add new time functions with nanosecond resolution
+ PEP written and implemented by Victor Stinner
+
+
Other Language Changes
======================
@@ -313,6 +339,15 @@ separately. (Contributed by Barry Warsaw in :issue:`1198569`.)
time
----
+The :pep:`564` added six new functions with nanosecond resolution:
+
+* :func:`time.clock_gettime_ns`
+* :func:`time.clock_settime_ns`
+* :func:`time.monotonic_ns`
+* :func:`time.perf_counter_ns`
+* :func:`time.process_time_ns`
+* :func:`time.time_ns`
+
Add new clock identifiers:
* :data:`time.CLOCK_BOOTTIME` (Linux): Identical to
diff --git a/Include/pytime.h b/Include/pytime.h
index 9f489180fff..4870a9df5b4 100644
--- a/Include/pytime.h
+++ b/Include/pytime.h
@@ -85,7 +85,11 @@ PyAPI_FUNC(_PyTime_t) _PyTime_FromSeconds(int seconds);
((_PyTime_t)(seconds) * (1000 * 1000 * 1000))
/* Create a timestamp from a number of nanoseconds. */
-PyAPI_FUNC(_PyTime_t) _PyTime_FromNanoseconds(long long ns);
+PyAPI_FUNC(_PyTime_t) _PyTime_FromNanoseconds(_PyTime_t ns);
+
+/* Create a timestamp from nanoseconds (Python int). */
+PyAPI_FUNC(int) _PyTime_FromNanosecondsObject(_PyTime_t *t,
+ PyObject *obj);
/* Convert a number of seconds (Python float or int) to a timetamp.
Raise an exception and return -1 on error, return 0 on success. */
@@ -114,6 +118,10 @@ PyAPI_FUNC(_PyTime_t) _PyTime_AsMicroseconds(_PyTime_t t,
object. */
PyAPI_FUNC(PyObject *) _PyTime_AsNanosecondsObject(_PyTime_t t);
+/* Create a timestamp from a timeval structure.
+ Raise an exception and return -1 on overflow, return 0 on success. */
+PyAPI_FUNC(int) _PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv);
+
/* Convert a timestamp to a timeval structure (microsecond resolution).
tv_usec is always positive.
Raise an exception and return -1 if the conversion overflowed,
@@ -140,12 +148,22 @@ PyAPI_FUNC(int) _PyTime_AsTimevalTime_t(
_PyTime_round_t round);
#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_KQUEUE)
+/* Create a timestamp from a timespec structure.
+ Raise an exception and return -1 on overflow, return 0 on success. */
+PyAPI_FUNC(int) _PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts);
+
/* Convert a timestamp to a timespec structure (nanosecond resolution).
tv_nsec is always positive.
Raise an exception and return -1 on error, return 0 on success. */
PyAPI_FUNC(int) _PyTime_AsTimespec(_PyTime_t t, struct timespec *ts);
#endif
+/* Compute ticks * mul / div.
+ The caller must ensure that ((div - 1) * mul) cannot overflow. */
+PyAPI_FUNC(_PyTime_t) _PyTime_MulDiv(_PyTime_t ticks,
+ _PyTime_t mul,
+ _PyTime_t div);
+
/* Get the current time from the system clock.
The function cannot fail. _PyTime_Init() ensures that the system clock
diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py
index eb73af51ac8..4d57bfbf9ab 100644
--- a/Lib/test/test_os.py
+++ b/Lib/test/test_os.py
@@ -3549,6 +3549,23 @@ def test_bad_pathlike(self):
self.assertRaises(ZeroDivisionError, self.fspath,
_PathLike(ZeroDivisionError()))
+
+class TimesTests(unittest.TestCase):
+ def test_times(self):
+ times = os.times()
+ self.assertIsInstance(times, os.times_result)
+
+ for field in ('user', 'system', 'children_user', 'children_system',
+ 'elapsed'):
+ value = getattr(times, field)
+ self.assertIsInstance(value, float)
+
+ if os.name == 'nt':
+ self.assertEqual(times.children_user, 0)
+ self.assertEqual(times.children_system, 0)
+ self.assertEqual(times.elapsed, 0)
+
+
# Only test if the C version is provided, otherwise TestPEP519 already tested
# the pure Python implementation.
if hasattr(os, "_fspath"):
diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py
index a08fd1822b0..b44646da709 100644
--- a/Lib/test/test_time.py
+++ b/Lib/test/test_time.py
@@ -64,6 +64,27 @@ def test_time(self):
self.assertFalse(info.monotonic)
self.assertTrue(info.adjustable)
+ def test_time_ns_type(self):
+ def check_ns(sec, ns):
+ self.assertIsInstance(ns, int)
+
+ sec_ns = int(sec * 1e9)
+ # tolerate a difference of 50 ms
+ self.assertLess((sec_ns - ns), 50 ** 6, (sec, ns))
+
+ check_ns(time.time(),
+ time.time_ns())
+ check_ns(time.monotonic(),
+ time.monotonic_ns())
+ check_ns(time.perf_counter(),
+ time.perf_counter_ns())
+ check_ns(time.process_time(),
+ time.process_time_ns())
+
+ if hasattr(time, 'clock_gettime'):
+ check_ns(time.clock_gettime(time.CLOCK_REALTIME),
+ time.clock_gettime_ns(time.CLOCK_REALTIME))
+
def test_clock(self):
with self.assertWarns(DeprecationWarning):
time.clock()
@@ -76,7 +97,8 @@ def test_clock(self):
@unittest.skipUnless(hasattr(time, 'clock_gettime'),
'need time.clock_gettime()')
def test_clock_realtime(self):
- time.clock_gettime(time.CLOCK_REALTIME)
+ t = time.clock_gettime(time.CLOCK_REALTIME)
+ self.assertIsInstance(t, float)
@unittest.skipUnless(hasattr(time, 'clock_gettime'),
'need time.clock_gettime()')
diff --git a/Misc/NEWS.d/next/Library/2017-10-13-23-35-47.bpo-31784.6e57bd.rst b/Misc/NEWS.d/next/Library/2017-10-13-23-35-47.bpo-31784.6e57bd.rst
new file mode 100644
index 00000000000..560c82a0ae0
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2017-10-13-23-35-47.bpo-31784.6e57bd.rst
@@ -0,0 +1,5 @@
+Implement the :pep:`564`, add new 6 new functions with nanosecond resolution to
+the :mod:`time` module: :func:`~time.clock_gettime_ns`,
+:func:`~time.clock_settime_ns`, :func:`~time.monotonic_ns`,
+:func:`~time.perf_counter_ns`, :func:`~time.process_time_ns`,
+:func:`~time.time_ns`.
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index 1f71a09974e..52108091f56 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -3946,13 +3946,16 @@ test_pytime_fromsecondsobject(PyObject *self, PyObject *args)
static PyObject *
test_pytime_assecondsdouble(PyObject *self, PyObject *args)
{
- long long ns;
+ PyObject *obj;
_PyTime_t ts;
double d;
- if (!PyArg_ParseTuple(args, "L", &ns))
+ if (!PyArg_ParseTuple(args, "O", &obj)) {
+ return NULL;
+ }
+ if (_PyTime_FromNanosecondsObject(&ts, obj) < 0) {
return NULL;
- ts = _PyTime_FromNanoseconds(ns);
+ }
d = _PyTime_AsSecondsDouble(ts);
return PyFloat_FromDouble(d);
}
@@ -3960,23 +3963,28 @@ test_pytime_assecondsdouble(PyObject *self, PyObject *args)
static PyObject *
test_PyTime_AsTimeval(PyObject *self, PyObject *args)
{
- long long ns;
+ PyObject *obj;
int round;
_PyTime_t t;
struct timeval tv;
PyObject *seconds;
- if (!PyArg_ParseTuple(args, "Li", &ns, &round))
+ if (!PyArg_ParseTuple(args, "Oi", &obj, &round))
return NULL;
- if (check_time_rounding(round) < 0)
+ if (check_time_rounding(round) < 0) {
return NULL;
- t = _PyTime_FromNanoseconds(ns);
- if (_PyTime_AsTimeval(t, &tv, round) < 0)
+ }
+ if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
return NULL;
+ }
+ if (_PyTime_AsTimeval(t, &tv, round) < 0) {
+ return NULL;
+ }
seconds = PyLong_FromLongLong(tv.tv_sec);
- if (seconds == NULL)
+ if (seconds == NULL) {
return NULL;
+ }
return Py_BuildValue("Nl", seconds, tv.tv_usec);
}
@@ -3984,15 +3992,19 @@ test_PyTime_AsTimeval(PyObject *self, PyObject *args)
static PyObject *
test_PyTime_AsTimespec(PyObject *self, PyObject *args)
{
- long long ns;
+ PyObject *obj;
_PyTime_t t;
struct timespec ts;
- if (!PyArg_ParseTuple(args, "L", &ns))
+ if (!PyArg_ParseTuple(args, "O", &obj)) {
return NULL;
- t = _PyTime_FromNanoseconds(ns);
- if (_PyTime_AsTimespec(t, &ts) == -1)
+ }
+ if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
return NULL;
+ }
+ if (_PyTime_AsTimespec(t, &ts) == -1) {
+ return NULL;
+ }
return Py_BuildValue("Nl", _PyLong_FromTime_t(ts.tv_sec), ts.tv_nsec);
}
#endif
@@ -4000,15 +4012,19 @@ test_PyTime_AsTimespec(PyObject *self, PyObject *args)
static PyObject *
test_PyTime_AsMilliseconds(PyObject *self, PyObject *args)
{
- long long ns;
+ PyObject *obj;
int round;
_PyTime_t t, ms;
- if (!PyArg_ParseTuple(args, "Li", &ns, &round))
+ if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) {
return NULL;
- if (check_time_rounding(round) < 0)
+ }
+ if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
+ return NULL;
+ }
+ if (check_time_rounding(round) < 0) {
return NULL;
- t = _PyTime_FromNanoseconds(ns);
+ }
ms = _PyTime_AsMilliseconds(t, round);
/* This conversion rely on the fact that _PyTime_t is a number of
nanoseconds */
@@ -4018,15 +4034,18 @@ test_PyTime_AsMilliseconds(PyObject *self, PyObject *args)
static PyObject *
test_PyTime_AsMicroseconds(PyObject *self, PyObject *args)
{
- long long ns;
+ PyObject *obj;
int round;
_PyTime_t t, ms;
- if (!PyArg_ParseTuple(args, "Li", &ns, &round))
+ if (!PyArg_ParseTuple(args, "Oi", &obj, &round))
return NULL;
- if (check_time_rounding(round) < 0)
+ if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
return NULL;
- t = _PyTime_FromNanoseconds(ns);
+ }
+ if (check_time_rounding(round) < 0) {
+ return NULL;
+ }
ms = _PyTime_AsMicroseconds(t, round);
/* This conversion rely on the fact that _PyTime_t is a number of
nanoseconds */
diff --git a/Modules/timemodule.c b/Modules/timemodule.c
index 347c8282d8e..37abeb95077 100644
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -34,57 +34,90 @@
#endif /* MS_WINDOWS */
#endif /* !__WATCOMC__ || __QNX__ */
+#define SEC_TO_NS (1000 * 1000 * 1000)
+
/* Forward declarations */
static int pysleep(_PyTime_t);
-static PyObject* floattime(_Py_clock_info_t *info);
+
+
+static PyObject*
+_PyFloat_FromPyTime(_PyTime_t t)
+{
+ double d = _PyTime_AsSecondsDouble(t);
+ return PyFloat_FromDouble(d);
+}
+
static PyObject *
time_time(PyObject *self, PyObject *unused)
{
- return floattime(NULL);
+ _PyTime_t t = _PyTime_GetSystemClock();
+ return _PyFloat_FromPyTime(t);
}
+
PyDoc_STRVAR(time_doc,
"time() -> floating point number\n\
\n\
Return the current time in seconds since the Epoch.\n\
Fractions of a second may be present if the system clock provides them.");
+static PyObject *
+time_time_ns(PyObject *self, PyObject *unused)
+{
+ _PyTime_t t = _PyTime_GetSystemClock();
+ return _PyTime_AsNanosecondsObject(t);
+}
+
+PyDoc_STRVAR(time_ns_doc,
+"time_ns() -> int\n\
+\n\
+Return the current time in nanoseconds since the Epoch.");
+
#if defined(HAVE_CLOCK)
#ifndef CLOCKS_PER_SEC
-#ifdef CLK_TCK
-#define CLOCKS_PER_SEC CLK_TCK
-#else
-#define CLOCKS_PER_SEC 1000000
-#endif
+# ifdef CLK_TCK
+# define CLOCKS_PER_SEC CLK_TCK
+# else
+# define CLOCKS_PER_SEC 1000000
+# endif
#endif
-static PyObject*
-_PyFloat_FromPyTime(_PyTime_t t)
+static int
+_PyTime_GetClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
{
- double d = _PyTime_AsSecondsDouble(t);
- return PyFloat_FromDouble(d);
-}
+ static int initialized = 0;
+ clock_t ticks;
-static PyObject *
-floatclock(_Py_clock_info_t *info)
-{
- clock_t value;
- value = clock();
- if (value == (clock_t)-1) {
- PyErr_SetString(PyExc_RuntimeError,
- "the processor time used is not available "
- "or its value cannot be represented");
- return NULL;
+ if (!initialized) {
+ initialized = 1;
+
+ /* must sure that _PyTime_MulDiv(ticks, SEC_TO_NS, CLOCKS_PER_SEC)
+ above cannot overflow */
+ if ((_PyTime_t)CLOCKS_PER_SEC > _PyTime_MAX / SEC_TO_NS) {
+ PyErr_SetString(PyExc_OverflowError,
+ "CLOCKS_PER_SEC is too large");
+ return -1;
+ }
}
+
if (info) {
info->implementation = "clock()";
info->resolution = 1.0 / (double)CLOCKS_PER_SEC;
info->monotonic = 1;
info->adjustable = 0;
}
- return PyFloat_FromDouble((double)value / CLOCKS_PER_SEC);
+
+ ticks = clock();
+ if (ticks == (clock_t)-1) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "the processor time used is not available "
+ "or its value cannot be represented");
+ return -1;
+ }
+ *tp = _PyTime_MulDiv(ticks, SEC_TO_NS, (_PyTime_t)CLOCKS_PER_SEC);
+ return 0;
}
#endif /* HAVE_CLOCK */
@@ -95,8 +128,7 @@ perf_counter(_Py_clock_info_t *info)
if (_PyTime_GetPerfCounterWithInfo(&t, info) < 0) {
return NULL;
}
- double d = _PyTime_AsSecondsDouble(t);
- return PyFloat_FromDouble(d);
+ return _PyFloat_FromPyTime(t);
}
#if defined(MS_WINDOWS) || defined(HAVE_CLOCK)
@@ -111,10 +143,15 @@ pyclock(_Py_clock_info_t *info)
"instead", 1) < 0) {
return NULL;
}
+
#ifdef MS_WINDOWS
return perf_counter(info);
#else
- return floatclock(info);
+ _PyTime_t t;
+ if (_PyTime_GetClockWithInfo(&t, info) < 0) {
+ return NULL;
+ }
+ return _PyFloat_FromPyTime(t);
#endif
}
@@ -140,8 +177,9 @@ time_clock_gettime(PyObject *self, PyObject *args)
int clk_id;
struct timespec tp;
- if (!PyArg_ParseTuple(args, "i:clock_gettime", &clk_id))
+ if (!PyArg_ParseTuple(args, "i:clock_gettime", &clk_id)) {
return NULL;
+ }
ret = clock_gettime((clockid_t)clk_id, &tp);
if (ret != 0) {
@@ -152,9 +190,37 @@ time_clock_gettime(PyObject *self, PyObject *args)
}
PyDoc_STRVAR(clock_gettime_doc,
-"clock_gettime(clk_id) -> floating point number\n\
+"clock_gettime(clk_id) -> float\n\
\n\
Return the time of the specified clock clk_id.");
+
+static PyObject *
+time_clock_gettime_ns(PyObject *self, PyObject *args)
+{
+ int ret;
+ int clk_id;
+ struct timespec ts;
+ _PyTime_t t;
+
+ if (!PyArg_ParseTuple(args, "i:clock_gettime", &clk_id)) {
+ return NULL;
+ }
+
+ ret = clock_gettime((clockid_t)clk_id, &ts);
+ if (ret != 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return NULL;
+ }
+ if (_PyTime_FromTimespec(&t, &ts) < 0) {
+ return NULL;
+ }
+ return _PyTime_AsNanosecondsObject(t);
+}
+
+PyDoc_STRVAR(clock_gettime_ns_doc,
+"clock_gettime_ns(clk_id) -> int\n\
+\n\
+Return the time of the specified clock clk_id as nanoseconds.");
#endif /* HAVE_CLOCK_GETTIME */
#ifdef HAVE_CLOCK_SETTIME
@@ -188,6 +254,39 @@ PyDoc_STRVAR(clock_settime_doc,
"clock_settime(clk_id, time)\n\
\n\
Set the time of the specified clock clk_id.");
+
+static PyObject *
+time_clock_settime_ns(PyObject *self, PyObject *args)
+{
+ int clk_id;
+ PyObject *obj;
+ _PyTime_t t;
+ struct timespec ts;
+ int ret;
+
+ if (!PyArg_ParseTuple(args, "iO:clock_settime", &clk_id, &obj)) {
+ return NULL;
+ }
+
+ if (_PyTime_FromNanosecondsObject(&t, obj) < 0) {
+ return NULL;
+ }
+ if (_PyTime_AsTimespec(t, &ts) == -1) {
+ return NULL;
+ }
+
+ ret = clock_settime((clockid_t)clk_id, &ts);
+ if (ret != 0) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(clock_settime_ns_doc,
+"clock_settime_ns(clk_id, time)\n\
+\n\
+Set the time of the specified clock clk_id with nanoseconds.");
#endif /* HAVE_CLOCK_SETTIME */
#ifdef HAVE_CLOCK_GETRES
@@ -927,26 +1026,28 @@ should not be relied on.");
#endif /* HAVE_WORKING_TZSET */
static PyObject *
-pymonotonic(_Py_clock_info_t *info)
+time_monotonic(PyObject *self, PyObject *unused)
{
- _PyTime_t t;
- if (_PyTime_GetMonotonicClockWithInfo(&t, info) < 0) {
- assert(info != NULL);
- return NULL;
- }
+ _PyTime_t t = _PyTime_GetMonotonicClock();
return _PyFloat_FromPyTime(t);
}
+PyDoc_STRVAR(monotonic_doc,
+"monotonic() -> float\n\
+\n\
+Monotonic clock, cannot go backward.");
+
static PyObject *
-time_monotonic(PyObject *self, PyObject *unused)
+time_monotonic_ns(PyObject *self, PyObject *unused)
{
- return pymonotonic(NULL);
+ _PyTime_t t = _PyTime_GetMonotonicClock();
+ return _PyTime_AsNanosecondsObject(t);
}
-PyDoc_STRVAR(monotonic_doc,
-"monotonic() -> float\n\
+PyDoc_STRVAR(monotonic_ns_doc,
+"monotonic_ns() -> int\n\
\n\
-Monotonic clock, cannot go backward.");
+Monotonic clock, cannot go backward, as nanoseconds.");
static PyObject *
time_perf_counter(PyObject *self, PyObject *unused)
@@ -959,47 +1060,61 @@ PyDoc_STRVAR(perf_counter_doc,
\n\
Performance counter for benchmarking.");
-static PyObject*
-py_process_time(_Py_clock_info_t *info)
+static PyObject *
+time_perf_counter_ns(PyObject *self, PyObject *unused)
+{
+ _PyTime_t t = _PyTime_GetPerfCounter();
+ return _PyTime_AsNanosecondsObject(t);
+}
+
+PyDoc_STRVAR(perf_counter_ns_doc,
+"perf_counter_ns() -> int\n\
+\n\
+Performance counter for benchmarking as nanoseconds.");
+
+static int
+_PyTime_GetProcessTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
{
#if defined(MS_WINDOWS)
HANDLE process;
FILETIME creation_time, exit_time, kernel_time, user_time;
ULARGE_INTEGER large;
- double total;
+ _PyTime_t ktime, utime, t;
BOOL ok;
process = GetCurrentProcess();
- ok = GetProcessTimes(process, &creation_time, &exit_time, &kernel_time, &user_time);
- if (!ok)
- return PyErr_SetFromWindowsErr(0);
+ ok = GetProcessTimes(process, &creation_time, &exit_time,
+ &kernel_time, &user_time);
+ if (!ok) {
+ PyErr_SetFromWindowsErr(0);
+ return -1;
+ }
- large.u.LowPart = kernel_time.dwLowDateTime;
- large.u.HighPart = kernel_time.dwHighDateTime;
- total = (double)large.QuadPart;
- large.u.LowPart = user_time.dwLowDateTime;
- large.u.HighPart = user_time.dwHighDateTime;
- total += (double)large.QuadPart;
if (info) {
info->implementation = "GetProcessTimes()";
info->resolution = 1e-7;
info->monotonic = 1;
info->adjustable = 0;
}
- return PyFloat_FromDouble(total * 1e-7);
-#else
-#if defined(HAVE_SYS_RESOURCE_H)
- struct rusage ru;
-#endif
-#ifdef HAVE_TIMES
- struct tms t;
- static long ticks_per_second = -1;
-#endif
+ large.u.LowPart = kernel_time.dwLowDateTime;
+ large.u.HighPart = kernel_time.dwHighDateTime;
+ ktime = large.QuadPart;
+
+ large.u.LowPart = user_time.dwLowDateTime;
+ large.u.HighPart = user_time.dwHighDateTime;
+ utime = large.QuadPart;
+
+ /* ktime and utime have a resolution of 100 nanoseconds */
+ t = _PyTime_FromNanoseconds((ktime + utime) * 100);
+ *tp = t;
+ return 0;
+#else
+ /* clock_gettime */
#if defined(HAVE_CLOCK_GETTIME) \
&& (defined(CLOCK_PROCESS_CPUTIME_ID) || defined(CLOCK_PROF))
- struct timespec tp;
+ struct timespec ts;
#ifdef CLOCK_PROF
const clockid_t clk_id = CLOCK_PROF;
const char *function = "clock_gettime(CLOCK_PROF)";
@@ -1008,75 +1123,117 @@ py_process_time(_Py_clock_info_t *info)
const char *function = "clock_gettime(CLOCK_PROCESS_CPUTIME_ID)";
#endif
- if (clock_gettime(clk_id, &tp) == 0) {
+ if (clock_gettime(clk_id, &ts) == 0) {
if (info) {
struct timespec res;
info->implementation = function;
info->monotonic = 1;
info->adjustable = 0;
- if (clock_getres(clk_id, &res) == 0)
- info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
- else
- info->resolution = 1e-9;
+ if (clock_getres(clk_id, &res)) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return -1;
+ }
+ info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
}
- return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9);
+
+ if (_PyTime_FromTimespec(tp, &ts) < 0) {
+ return -1;
+ }
+ return 0;
}
#endif
+ /* getrusage(RUSAGE_SELF) */
#if defined(HAVE_SYS_RESOURCE_H)
+ struct rusage ru;
+
if (getrusage(RUSAGE_SELF, &ru) == 0) {
- double total;
- total = ru.ru_utime.tv_sec + ru.ru_utime.tv_usec * 1e-6;
- total += ru.ru_stime.tv_sec + ru.ru_stime.tv_usec * 1e-6;
+ _PyTime_t utime, stime;
+
if (info) {
info->implementation = "getrusage(RUSAGE_SELF)";
info->monotonic = 1;
info->adjustable = 0;
info->resolution = 1e-6;
}
- return PyFloat_FromDouble(total);
+
+ if (_PyTime_FromTimeval(&utime, &ru.ru_utime) < 0) {
+ return -1;
+ }
+ if (_PyTime_FromTimeval(&stime, &ru.ru_stime) < 0) {
+ return -1;
+ }
+
+ _PyTime_t total = utime + utime;
+ *tp = total;
+ return 0;
}
#endif
+ /* times() */
#ifdef HAVE_TIMES
+ struct tms t;
+
if (times(&t) != (clock_t)-1) {
- double total;
+ static long ticks_per_second = -1;
if (ticks_per_second == -1) {
+ long freq;
#if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
- ticks_per_second = sysconf(_SC_CLK_TCK);
- if (ticks_per_second < 1)
- ticks_per_second = -1;
+ freq = sysconf(_SC_CLK_TCK);
+ if (freq < 1) {
+ freq = -1;
+ }
#elif defined(HZ)
- ticks_per_second = HZ;
+ freq = HZ;
#else
- ticks_per_second = 60; /* magic fallback value; may be bogus */
+ freq = 60; /* magic fallback value; may be bogus */
#endif
+
+ if (freq != -1) {
+ /* check that _PyTime_MulDiv(t, SEC_TO_NS, ticks_per_second)
+ cannot overflow below */
+ if ((_PyTime_t)freq > _PyTime_MAX / SEC_TO_NS) {
+ PyErr_SetString(PyExc_OverflowError,
+ "_SC_CLK_TCK is too large");
+ return -1;
+ }
+
+ ticks_per_second = freq;
+ }
}
if (ticks_per_second != -1) {
- total = (double)t.tms_utime / ticks_per_second;
- total += (double)t.tms_stime / ticks_per_second;
if (info) {
info->implementation = "times()";
info->monotonic = 1;
info->adjustable = 0;
- info->resolution = 1.0 / ticks_per_second;
+ info->resolution = 1.0 / (double)ticks_per_second;
}
- return PyFloat_FromDouble(total);
+
+ _PyTime_t total;
+ total = _PyTime_MulDiv(t.tms_utime, SEC_TO_NS, ticks_per_second);
+ total += _PyTime_MulDiv(t.tms_stime, SEC_TO_NS, ticks_per_second);
+ *tp = total;
+ return 0;
}
}
#endif
+ /* clock */
/* Currently, Python 3 requires clock() to build: see issue #22624 */
- return floatclock(info);
+ return _PyTime_GetClockWithInfo(tp, info);
#endif
}
static PyObject *
time_process_time(PyObject *self, PyObject *unused)
{
- return py_process_time(NULL);
+ _PyTime_t t;
+ if (_PyTime_GetProcessTimeWithInfo(&t, NULL) < 0) {
+ return NULL;
+ }
+ return _PyFloat_FromPyTime(t);
}
PyDoc_STRVAR(process_time_doc,
@@ -1084,6 +1241,22 @@ PyDoc_STRVAR(process_time_doc,
\n\
Process time for profiling: sum of the kernel and user-space CPU time.");
+static PyObject *
+time_process_time_ns(PyObject *self, PyObject *unused)
+{
+ _PyTime_t t;
+ if (_PyTime_GetProcessTimeWithInfo(&t, NULL) < 0) {
+ return NULL;
+ }
+ return _PyTime_AsNanosecondsObject(t);
+}
+
+PyDoc_STRVAR(process_time_ns_doc,
+"process_time() -> int\n\
+\n\
+Process time for profiling as nanoseconds:\n\
+sum of the kernel and user-space CPU time.");
+
static PyObject *
time_get_clock_info(PyObject *self, PyObject *args)
@@ -1091,9 +1264,11 @@ time_get_clock_info(PyObject *self, PyObject *args)
char *name;
_Py_clock_info_t info;
PyObject *obj = NULL, *dict, *ns;
+ _PyTime_t t;
- if (!PyArg_ParseTuple(args, "s:get_clock_info", &name))
+ if (!PyArg_ParseTuple(args, "s:get_clock_info", &name)) {
return NULL;
+ }
#ifdef Py_DEBUG
info.implementation = NULL;
@@ -1107,61 +1282,84 @@ time_get_clock_info(PyObject *self, PyObject *args)
info.resolution = 1.0;
#endif
- if (strcmp(name, "time") == 0)
- obj = floattime(&info);
+ if (strcmp(name, "time") == 0) {
+ if (_PyTime_GetSystemClockWithInfo(&t, &info) < 0) {
+ return NULL;
+ }
+ }
#ifdef PYCLOCK
- else if (strcmp(name, "clock") == 0)
+ else if (strcmp(name, "clock") == 0) {
obj = pyclock(&info);
+ if (obj == NULL) {
+ return NULL;
+ }
+ Py_DECREF(obj);
+ }
#endif
- else if (strcmp(name, "monotonic") == 0)
- obj = pymonotonic(&info);
- else if (strcmp(name, "perf_counter") == 0)
- obj = perf_counter(&info);
- else if (strcmp(name, "process_time") == 0)
- obj = py_process_time(&info);
+ else if (strcmp(name, "monotonic") == 0) {
+ if (_PyTime_GetMonotonicClockWithInfo(&t, &info) < 0) {
+ return NULL;
+ }
+ }
+ else if (strcmp(name, "perf_counter") == 0) {
+ if (_PyTime_GetPerfCounterWithInfo(&t, &info) < 0) {
+ return NULL;
+ }
+ }
+ else if (strcmp(name, "process_time") == 0) {
+ if (_PyTime_GetProcessTimeWithInfo(&t, &info) < 0) {
+ return NULL;
+ }
+ }
else {
PyErr_SetString(PyExc_ValueError, "unknown clock");
return NULL;
}
- if (obj == NULL)
- return NULL;
- Py_DECREF(obj);
dict = PyDict_New();
- if (dict == NULL)
+ if (dict == NULL) {
return NULL;
+ }
assert(info.implementation != NULL);
obj = PyUnicode_FromString(info.implementation);
- if (obj == NULL)
+ if (obj == NULL) {
goto error;
- if (PyDict_SetItemString(dict, "implementation", obj) == -1)
+ }
+ if (PyDict_SetItemString(dict, "implementation", obj) == -1) {
goto error;
+ }
Py_CLEAR(obj);
assert(info.monotonic != -1);
obj = PyBool_FromLong(info.monotonic);
- if (obj == NULL)
+ if (obj == NULL) {
goto error;
- if (PyDict_SetItemString(dict, "monotonic", obj) == -1)
+ }
+ if (PyDict_SetItemString(dict, "monotonic", obj) == -1) {
goto error;
+ }
Py_CLEAR(obj);
assert(info.adjustable != -1);
obj = PyBool_FromLong(info.adjustable);
- if (obj == NULL)
+ if (obj == NULL) {
goto error;
- if (PyDict_SetItemString(dict, "adjustable", obj) == -1)
+ }
+ if (PyDict_SetItemString(dict, "adjustable", obj) == -1) {
goto error;
+ }
Py_CLEAR(obj);
assert(info.resolution > 0.0);
assert(info.resolution <= 1.0);
obj = PyFloat_FromDouble(info.resolution);
- if (obj == NULL)
+ if (obj == NULL) {
goto error;
- if (PyDict_SetItemString(dict, "resolution", obj) == -1)
+ }
+ if (PyDict_SetItemString(dict, "resolution", obj) == -1) {
goto error;
+ }
Py_CLEAR(obj);
ns = _PyNamespace_New(dict);
@@ -1284,14 +1482,17 @@ PyInit_timezone(PyObject *m) {
static PyMethodDef time_methods[] = {
{"time", time_time, METH_NOARGS, time_doc},
+ {"time_ns", time_time_ns, METH_NOARGS, time_ns_doc},
#ifdef PYCLOCK
{"clock", time_clock, METH_NOARGS, clock_doc},
#endif
#ifdef HAVE_CLOCK_GETTIME
{"clock_gettime", time_clock_gettime, METH_VARARGS, clock_gettime_doc},
+ {"clock_gettime_ns",time_clock_gettime_ns, METH_VARARGS, clock_gettime_ns_doc},
#endif
#ifdef HAVE_CLOCK_SETTIME
{"clock_settime", time_clock_settime, METH_VARARGS, clock_settime_doc},
+ {"clock_settime_ns",time_clock_settime_ns, METH_VARARGS, clock_settime_ns_doc},
#endif
#ifdef HAVE_CLOCK_GETRES
{"clock_getres", time_clock_getres, METH_VARARGS, clock_getres_doc},
@@ -1315,8 +1516,11 @@ static PyMethodDef time_methods[] = {
{"tzset", time_tzset, METH_NOARGS, tzset_doc},
#endif
{"monotonic", time_monotonic, METH_NOARGS, monotonic_doc},
+ {"monotonic_ns", time_monotonic_ns, METH_NOARGS, monotonic_ns_doc},
{"process_time", time_process_time, METH_NOARGS, process_time_doc},
+ {"process_time_ns", time_process_time_ns, METH_NOARGS, process_time_ns_doc},
{"perf_counter", time_perf_counter, METH_NOARGS, perf_counter_doc},
+ {"perf_counter_ns", time_perf_counter_ns, METH_NOARGS, perf_counter_ns_doc},
{"get_clock_info", time_get_clock_info, METH_VARARGS, get_clock_info_doc},
{NULL, NULL} /* sentinel */
};
@@ -1411,18 +1615,6 @@ PyInit_time(void)
return m;
}
-static PyObject*
-floattime(_Py_clock_info_t *info)
-{
- _PyTime_t t;
- if (_PyTime_GetSystemClockWithInfo(&t, info) < 0) {
- assert(info != NULL);
- return NULL;
- }
- return _PyFloat_FromPyTime(t);
-}
-
-
/* Implement pysleep() for various platforms.
When interrupted (or when another error occurs), return -1 and
set an exception; else return 0. */
diff --git a/Python/pytime.c b/Python/pytime.c
index f19bb3673e4..5a98d1d3297 100644
--- a/Python/pytime.c
+++ b/Python/pytime.c
@@ -43,8 +43,7 @@ _PyTime_overflow(void)
}
-#if defined(MS_WINDOWS) || defined(__APPLE__)
-Py_LOCAL_INLINE(_PyTime_t)
+_PyTime_t
_PyTime_MulDiv(_PyTime_t ticks, _PyTime_t mul, _PyTime_t div)
{
_PyTime_t intpart, remaining;
@@ -60,7 +59,6 @@ _PyTime_MulDiv(_PyTime_t ticks, _PyTime_t mul, _PyTime_t div)
remaining /= div;
return intpart * mul + remaining;
}
-#endif /* defined(MS_WINDOWS) || defined(__APPLE__) */
time_t
@@ -254,19 +252,44 @@ _PyTime_FromSeconds(int seconds)
}
_PyTime_t
-_PyTime_FromNanoseconds(long long ns)
+_PyTime_FromNanoseconds(_PyTime_t ns)
+{
+ /* _PyTime_t already uses nanosecond resolution, no conversion needed */
+ return ns;
+}
+
+int
+_PyTime_FromNanosecondsObject(_PyTime_t *tp, PyObject *obj)
{
+ long long nsec;
_PyTime_t t;
- Py_BUILD_ASSERT(sizeof(long long) <= sizeof(_PyTime_t));
- t = Py_SAFE_DOWNCAST(ns, long long, _PyTime_t);
- return t;
+
+ if (!PyLong_Check(obj)) {
+ PyErr_Format(PyExc_TypeError, "expect int, got %s",
+ Py_TYPE(obj)->tp_name);
+ return -1;
+ }
+
+ Py_BUILD_ASSERT(sizeof(long long) == sizeof(_PyTime_t));
+ nsec = PyLong_AsLongLong(obj);
+ if (nsec == -1 && PyErr_Occurred()) {
+ if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
+ _PyTime_overflow();
+ }
+ return -1;
+ }
+
+ /* _PyTime_t already uses nanosecond resolution, no conversion needed */
+ t = (_PyTime_t)nsec;
+ *tp = t;
+ return 0;
}
#ifdef HAVE_CLOCK_GETTIME
static int
-_PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts, int raise)
+pytime_fromtimespec(_PyTime_t *tp, struct timespec *ts, int raise)
{
- _PyTime_t t;
+ _PyTime_t t, nsec;
int res = 0;
Py_BUILD_ASSERT(sizeof(ts->tv_sec) <= sizeof(_PyTime_t));
@@ -277,19 +300,42 @@ _PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts, int raise)
_PyTime_overflow();
}
res = -1;
+ t = (t > 0) ? _PyTime_MAX : _PyTime_MIN;
+ }
+ else {
+ t = t * SEC_TO_NS;
}
- t = t * SEC_TO_NS;
- t += ts->tv_nsec;
+ nsec = ts->tv_nsec;
+ /* The following test is written for positive only nsec */
+ assert(nsec >= 0);
+ if (t > _PyTime_MAX - nsec) {
+ if (raise) {
+ _PyTime_overflow();
+ }
+ res = -1;
+ t = _PyTime_MAX;
+ }
+ else {
+ t += nsec;
+ }
*tp = t;
return res;
}
-#elif !defined(MS_WINDOWS)
+
+int
+_PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts)
+{
+ return pytime_fromtimespec(tp, ts, 1);
+}
+#endif
+
+#if !defined(MS_WINDOWS)
static int
-_PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv, int raise)
+pytime_fromtimeval(_PyTime_t *tp, struct timeval *tv, int raise)
{
- _PyTime_t t;
+ _PyTime_t t, usec;
int res = 0;
Py_BUILD_ASSERT(sizeof(tv->tv_sec) <= sizeof(_PyTime_t));
@@ -300,14 +346,35 @@ _PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv, int raise)
_PyTime_overflow();
}
res = -1;
+ t = (t > 0) ? _PyTime_MAX : _PyTime_MIN;
+ }
+ else {
+ t = t * SEC_TO_NS;
}
- t = t * SEC_TO_NS;
- t += (_PyTime_t)tv->tv_usec * US_TO_NS;
+ usec = (_PyTime_t)tv->tv_usec * US_TO_NS;
+ /* The following test is written for positive only usec */
+ assert(usec >= 0);
+ if (t > _PyTime_MAX - usec) {
+ if (raise) {
+ _PyTime_overflow();
+ }
+ res = -1;
+ t = _PyTime_MAX;
+ }
+ else {
+ t += usec;
+ }
*tp = t;
return res;
}
+
+int
+_PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv)
+{
+ return pytime_fromtimeval(tp, tv, 1);
+}
#endif
static int
@@ -632,7 +699,7 @@ pygettimeofday(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
}
return -1;
}
- if (_PyTime_FromTimespec(tp, &ts, raise) < 0) {
+ if (pytime_fromtimespec(tp, &ts, raise) < 0) {
return -1;
}
@@ -662,7 +729,7 @@ pygettimeofday(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
}
return -1;
}
- if (_PyTime_FromTimeval(tp, &tv, raise) < 0) {
+ if (pytime_fromtimeval(tp, &tv, raise) < 0) {
return -1;
}
@@ -841,7 +908,7 @@ pymonotonic(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
}
info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
}
- if (_PyTime_FromTimespec(tp, &ts, raise) < 0) {
+ if (pytime_fromtimespec(tp, &ts, raise) < 0) {
return -1;
}
#endif
1
0
Nov. 2, 2017
https://github.com/python/cpython/commit/e314853d57450b2b9523157eebd405289a…
commit: e314853d57450b2b9523157eebd405289a795a0e
branch: master
author: Vincent Michel <vxgmichel(a)gmail.com>
committer: Berker Peksag <berker.peksag(a)gmail.com>
date: 2017-11-02T15:47:04+03:00
summary:
bpo-31307: Make ConfigParser.read() accept bytes objects (GH-3420)
files:
A Misc/NEWS.d/next/Library/2017-09-07-12-50-28.bpo-31307.AVBiNY.rst
M Doc/library/configparser.rst
M Lib/configparser.py
M Lib/test/test_configparser.py
diff --git a/Doc/library/configparser.rst b/Doc/library/configparser.rst
index acca6470111..dd8257720b7 100644
--- a/Doc/library/configparser.rst
+++ b/Doc/library/configparser.rst
@@ -995,7 +995,8 @@ ConfigParser Objects
Attempt to read and parse a list of filenames, returning a list of
filenames which were successfully parsed.
- If *filenames* is a string or :term:`path-like object`, it is treated as
+ If *filenames* is a string, a :class:`bytes` object or a
+ :term:`path-like object`, it is treated as
a single filename. If a file named in *filenames* cannot be opened, that
file will be ignored. This is designed so that you can specify a list of
potential configuration file locations (for example, the current
@@ -1022,6 +1023,9 @@ ConfigParser Objects
.. versionadded:: 3.6.1
The *filenames* parameter accepts a :term:`path-like object`.
+ .. versionadded:: 3.7
+ The *filenames* parameter accepts a :class:`bytes` object.
+
.. method:: read_file(f, source=None)
diff --git a/Lib/configparser.py b/Lib/configparser.py
index e172ac8b36f..33dc9b9046f 100644
--- a/Lib/configparser.py
+++ b/Lib/configparser.py
@@ -687,7 +687,7 @@ def read(self, filenames, encoding=None):
Return list of successfully read files.
"""
- if isinstance(filenames, (str, os.PathLike)):
+ if isinstance(filenames, (str, bytes, os.PathLike)):
filenames = [filenames]
read_ok = []
for filename in filenames:
diff --git a/Lib/test/test_configparser.py b/Lib/test/test_configparser.py
index d8969efc4db..4d07203b9da 100644
--- a/Lib/test/test_configparser.py
+++ b/Lib/test/test_configparser.py
@@ -740,6 +740,23 @@ def test_read_returns_file_list(self):
parsed_files = cf.read([])
self.assertEqual(parsed_files, [])
+ def test_read_returns_file_list_with_bytestring_path(self):
+ if self.delimiters[0] != '=':
+ self.skipTest('incompatible format')
+ file1_bytestring = support.findfile("cfgparser.1").encode()
+ # check when passing an existing bytestring path
+ cf = self.newconfig()
+ parsed_files = cf.read(file1_bytestring)
+ self.assertEqual(parsed_files, [file1_bytestring])
+ # check when passing an non-existing bytestring path
+ cf = self.newconfig()
+ parsed_files = cf.read(b'nonexistent-file')
+ self.assertEqual(parsed_files, [])
+ # check when passing both an existing and non-existing bytestring path
+ cf = self.newconfig()
+ parsed_files = cf.read([file1_bytestring, b'nonexistent-file'])
+ self.assertEqual(parsed_files, [file1_bytestring])
+
# shared by subclasses
def get_interpolation_config(self):
return self.fromstring(
diff --git a/Misc/NEWS.d/next/Library/2017-09-07-12-50-28.bpo-31307.AVBiNY.rst b/Misc/NEWS.d/next/Library/2017-09-07-12-50-28.bpo-31307.AVBiNY.rst
new file mode 100644
index 00000000000..7e649aa9d6e
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2017-09-07-12-50-28.bpo-31307.AVBiNY.rst
@@ -0,0 +1,2 @@
+Allow use of bytes objects for arguments to
+:meth:`configparser.ConfigParser.read`. Patch by Vincent Michel.
1
0
https://github.com/python/cpython/commit/a64ce973a3ad90e4f4a93c402e946c132f…
commit: a64ce973a3ad90e4f4a93c402e946c132f647a63
branch: master
author: Victor Stinner <victor.stinner(a)gmail.com>
committer: GitHub <noreply(a)github.com>
date: 2017-11-02T04:19:19-07:00
summary:
bpo-31917: Add 3 new clock identifiers (#4207)
Add new clock identfiers:
* time.CLOCK_BOOTTIME
* time.CLOCK_PROF
* time.CLOCK_UPTIME
files:
A Misc/NEWS.d/next/Library/2017-11-01-03-28-24.bpo-31917.DYQL0g.rst
M Doc/library/time.rst
M Doc/whatsnew/3.7.rst
M Modules/timemodule.c
diff --git a/Doc/library/time.rst b/Doc/library/time.rst
index c5d1e83e739..253df733bf3 100644
--- a/Doc/library/time.rst
+++ b/Doc/library/time.rst
@@ -663,6 +663,21 @@ Clock ID Constants
These constants are used as parameters for :func:`clock_getres` and
:func:`clock_gettime`.
+.. data:: CLOCK_BOOTTIME
+
+ Identical to :data:`CLOCK_MONOTONIC`, except it also includes any time that
+ the system is suspended.
+
+ This allows applications to get a suspend-aware monotonic clock without
+ having to deal with the complications of :data:`CLOCK_REALTIME`, which may
+ have discontinuities if the time is changed using ``settimeofday()`` or
+ similar.
+
+ Availability: Linux 2.6.39 or later.
+
+ .. versionadded:: 3.7
+
+
.. data:: CLOCK_HIGHRES
The Solaris OS has a ``CLOCK_HIGHRES`` timer that attempts to use an optimal
@@ -703,6 +718,15 @@ These constants are used as parameters for :func:`clock_getres` and
.. versionadded:: 3.3
+.. data:: CLOCK_PROF
+
+ High-resolution per-process timer from the CPU.
+
+ Availability: FreeBSD 3 or later, NetBSD 7 or later, OpenBSD.
+
+ .. versionadded:: 3.7
+
+
.. data:: CLOCK_THREAD_CPUTIME_ID
Thread-specific CPU-time clock.
@@ -712,6 +736,17 @@ These constants are used as parameters for :func:`clock_getres` and
.. versionadded:: 3.3
+.. data:: CLOCK_UPTIME
+
+ Time whose absolute value is the time the system has been running and not
+ suspended, providing accurate uptime measurement, both absolute and
+ interval.
+
+ Availability: FreeBSD 7 or later, OpenBSD 5.5 or later.
+
+ .. versionadded:: 3.7
+
+
The following constant is the only parameter that can be sent to
:func:`clock_settime`.
diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst
index d3c3c1f7537..d5836d509be 100644
--- a/Doc/whatsnew/3.7.rst
+++ b/Doc/whatsnew/3.7.rst
@@ -310,6 +310,20 @@ string
expression pattern for braced placeholders and non-braced placeholders
separately. (Contributed by Barry Warsaw in :issue:`1198569`.)
+time
+----
+
+Add new clock identifiers:
+
+* :data:`time.CLOCK_BOOTTIME` (Linux): Identical to
+ :data:`time.CLOCK_MONOTONIC`, except it also includes any time that the
+ system is suspended.
+* :data:`time.CLOCK_PROF` (FreeBSD, NetBSD and OpenBSD): High-resolution
+ per-process timer from the CPU.
+* :data:`time.CLOCK_UPTIME` (FreeBSD, OpenBSD): Time whose absolute value is
+ the time the system has been running and not suspended, providing accurate
+ uptime measurement, both absolute and interval.
+
unittest.mock
-------------
diff --git a/Misc/NEWS.d/next/Library/2017-11-01-03-28-24.bpo-31917.DYQL0g.rst b/Misc/NEWS.d/next/Library/2017-11-01-03-28-24.bpo-31917.DYQL0g.rst
new file mode 100644
index 00000000000..dbfe92ab0b0
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2017-11-01-03-28-24.bpo-31917.DYQL0g.rst
@@ -0,0 +1,2 @@
+Add 3 new clock identifiers: :data:`time.CLOCK_BOOTTIME`,
+:data:`time.CLOCK_PROF` and :data:`time.CLOCK_UPTIME`.
diff --git a/Modules/timemodule.c b/Modules/timemodule.c
index b5e168f9ec3..347c8282d8e 100644
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -1389,6 +1389,15 @@ PyInit_time(void)
#ifdef CLOCK_THREAD_CPUTIME_ID
PyModule_AddIntMacro(m, CLOCK_THREAD_CPUTIME_ID);
#endif
+#ifdef CLOCK_PROF
+ PyModule_AddIntMacro(m, CLOCK_PROF);
+#endif
+#ifdef CLOCK_BOOTTIME
+ PyModule_AddIntMacro(m, CLOCK_BOOTTIME);
+#endif
+#ifdef CLOCK_UPTIME
+ PyModule_AddIntMacro(m, CLOCK_UPTIME);
+#endif
if (!initialized) {
if (PyStructSequence_InitType2(&StructTimeType,
1
0
bpo-23699: Use a macro to reduce boilerplate code in rich comparison functions (GH-793)
by Nick Coghlan Nov. 2, 2017
by Nick Coghlan Nov. 2, 2017
Nov. 2, 2017
https://github.com/python/cpython/commit/e8b19656396381407ad91473af5da8b0d4…
commit: e8b19656396381407ad91473af5da8b0d4346e88
branch: master
author: stratakis <cstratak(a)redhat.com>
committer: Nick Coghlan <ncoghlan(a)gmail.com>
date: 2017-11-02T20:32:54+10:00
summary:
bpo-23699: Use a macro to reduce boilerplate code in rich comparison functions (GH-793)
files:
A Misc/NEWS.d/next/C API/2017-10-19-15-27-04.bpo-23699.-noVVc.rst
M Doc/c-api/typeobj.rst
M Include/object.h
M Misc/ACKS
M Modules/_datetimemodule.c
M Modules/_tkinter.c
M Modules/parsermodule.c
M Modules/selectmodule.c
M Objects/bytearrayobject.c
M Objects/bytesobject.c
M Objects/cellobject.c
M Objects/descrobject.c
M Objects/listobject.c
M Objects/longobject.c
M Objects/tupleobject.c
M Objects/unicodeobject.c
diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst
index 0b4577f5b95..3bdf45ad9b6 100644
--- a/Doc/c-api/typeobj.rst
+++ b/Doc/c-api/typeobj.rst
@@ -623,6 +623,22 @@ type objects) *must* have the :attr:`ob_size` field.
| :const:`Py_GE` | ``>=`` |
+----------------+------------+
+ The following macro is defined to ease writing rich comparison functions:
+
+ .. c:function:: PyObject *Py_RETURN_RICHCOMPARE(VAL_A, VAL_B, int op)
+
+ Return ``Py_True`` or ``Py_False`` from the function, depending on the
+ result of a comparison.
+ VAL_A and VAL_B must be orderable by C comparison operators (for example,
+ they may be C ints or floats). The third argument specifies the requested
+ operation, as for :c:func:`PyObject_RichCompare`.
+
+ The return value's reference count is properly incremented.
+
+ On error, sets an exception and returns NULL from the function.
+
+ .. versionadded:: 3.7
+
.. c:member:: Py_ssize_t PyTypeObject.tp_weaklistoffset
diff --git a/Include/object.h b/Include/object.h
index cb57359ea23..b7051f3f17e 100644
--- a/Include/object.h
+++ b/Include/object.h
@@ -931,6 +931,25 @@ PyAPI_DATA(PyObject) _Py_NotImplementedStruct; /* Don't use this directly */
#define Py_GT 4
#define Py_GE 5
+/*
+ * Macro for implementing rich comparisons
+ *
+ * Needs to be a macro because any C-comparable type can be used.
+ */
+#define Py_RETURN_RICHCOMPARE(val1, val2, op) \
+ do { \
+ switch (op) { \
+ case Py_EQ: if ((val1) == (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \
+ case Py_NE: if ((val1) != (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \
+ case Py_LT: if ((val1) < (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \
+ case Py_GT: if ((val1) > (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \
+ case Py_LE: if ((val1) <= (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \
+ case Py_GE: if ((val1) >= (val2)) Py_RETURN_TRUE; Py_RETURN_FALSE; \
+ default: \
+ Py_UNREACHABLE(); \
+ } \
+ } while (0)
+
#ifndef Py_LIMITED_API
/* Maps Py_LT to Py_GT, ..., Py_GE to Py_LE.
* Defined in object.c.
diff --git a/Misc/ACKS b/Misc/ACKS
index ac7a258df18..1bd3c047d89 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1646,7 +1646,7 @@ Mike Verdone
Jaap Vermeulen
Nikita Vetoshkin
Al Vezza
-Petr Victorin
+Petr Viktorin
Jacques A. Vidrine
John Viega
Dino Viehland
diff --git a/Misc/NEWS.d/next/C API/2017-10-19-15-27-04.bpo-23699.-noVVc.rst b/Misc/NEWS.d/next/C API/2017-10-19-15-27-04.bpo-23699.-noVVc.rst
new file mode 100644
index 00000000000..d873666eab2
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2017-10-19-15-27-04.bpo-23699.-noVVc.rst
@@ -0,0 +1,2 @@
+Add Py_RETURN_RICHCOMPARE macro to reduce boilerplate code in rich
+comparison functions.
diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c
index 09b557958a0..b50cddad5dd 100644
--- a/Modules/_datetimemodule.c
+++ b/Modules/_datetimemodule.c
@@ -1442,22 +1442,7 @@ build_struct_time(int y, int m, int d, int hh, int mm, int ss, int dstflag)
static PyObject *
diff_to_bool(int diff, int op)
{
- PyObject *result;
- int istrue;
-
- switch (op) {
- case Py_EQ: istrue = diff == 0; break;
- case Py_NE: istrue = diff != 0; break;
- case Py_LE: istrue = diff <= 0; break;
- case Py_GE: istrue = diff >= 0; break;
- case Py_LT: istrue = diff < 0; break;
- case Py_GT: istrue = diff > 0; break;
- default:
- Py_UNREACHABLE();
- }
- result = istrue ? Py_True : Py_False;
- Py_INCREF(result);
- return result;
+ Py_RETURN_RICHCOMPARE(diff, 0, op);
}
/* Raises a "can't compare" TypeError and returns NULL. */
diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c
index 005214e27f7..7123da58851 100644
--- a/Modules/_tkinter.c
+++ b/Modules/_tkinter.c
@@ -864,13 +864,10 @@ PyTclObject_repr(PyTclObject *self)
return repr;
}
-#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
-
static PyObject *
PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
{
int result;
- PyObject *v;
/* neither argument should be NULL, unless something's gone wrong */
if (self == NULL || other == NULL) {
@@ -880,8 +877,7 @@ PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
/* both arguments should be instances of PyTclObject */
if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
- v = Py_NotImplemented;
- goto finished;
+ Py_RETURN_NOTIMPLEMENTED;
}
if (self == other)
@@ -890,33 +886,7 @@ PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
else
result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
Tcl_GetString(((PyTclObject *)other)->value));
- /* Convert return value to a Boolean */
- switch (op) {
- case Py_EQ:
- v = TEST_COND(result == 0);
- break;
- case Py_NE:
- v = TEST_COND(result != 0);
- break;
- case Py_LE:
- v = TEST_COND(result <= 0);
- break;
- case Py_GE:
- v = TEST_COND(result >= 0);
- break;
- case Py_LT:
- v = TEST_COND(result < 0);
- break;
- case Py_GT:
- v = TEST_COND(result > 0);
- break;
- default:
- PyErr_BadArgument();
- return NULL;
- }
- finished:
- Py_INCREF(v);
- return v;
+ Py_RETURN_RICHCOMPARE(result, 0, op);
}
PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c
index 929f2deb16c..2b98be40e30 100644
--- a/Modules/parsermodule.c
+++ b/Modules/parsermodule.c
@@ -299,13 +299,10 @@ parser_compare_nodes(node *left, node *right)
*
*/
-#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
-
static PyObject *
parser_richcompare(PyObject *left, PyObject *right, int op)
{
int result;
- PyObject *v;
/* neither argument should be NULL, unless something's gone wrong */
if (left == NULL || right == NULL) {
@@ -315,8 +312,7 @@ parser_richcompare(PyObject *left, PyObject *right, int op)
/* both arguments should be instances of PyST_Object */
if (!PyST_Object_Check(left) || !PyST_Object_Check(right)) {
- v = Py_NotImplemented;
- goto finished;
+ Py_RETURN_NOTIMPLEMENTED;
}
if (left == right)
@@ -326,33 +322,7 @@ parser_richcompare(PyObject *left, PyObject *right, int op)
result = parser_compare_nodes(((PyST_Object *)left)->st_node,
((PyST_Object *)right)->st_node);
- /* Convert return value to a Boolean */
- switch (op) {
- case Py_EQ:
- v = TEST_COND(result == 0);
- break;
- case Py_NE:
- v = TEST_COND(result != 0);
- break;
- case Py_LE:
- v = TEST_COND(result <= 0);
- break;
- case Py_GE:
- v = TEST_COND(result >= 0);
- break;
- case Py_LT:
- v = TEST_COND(result < 0);
- break;
- case Py_GT:
- v = TEST_COND(result > 0);
- break;
- default:
- PyErr_BadArgument();
- return NULL;
- }
- finished:
- Py_INCREF(v);
- return v;
+ Py_RETURN_RICHCOMPARE(result, 0, op);
}
/* parser_newstobject(node* st)
diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c
index 1cde6e849c4..f2f5cc86cdb 100644
--- a/Modules/selectmodule.c
+++ b/Modules/selectmodule.c
@@ -1929,27 +1929,7 @@ kqueue_event_richcompare(kqueue_event_Object *s, kqueue_event_Object *o,
: 0;
#undef CMP
- switch (op) {
- case Py_EQ:
- result = (result == 0);
- break;
- case Py_NE:
- result = (result != 0);
- break;
- case Py_LE:
- result = (result <= 0);
- break;
- case Py_GE:
- result = (result >= 0);
- break;
- case Py_LT:
- result = (result < 0);
- break;
- case Py_GT:
- result = (result > 0);
- break;
- }
- return PyBool_FromLong((long)result);
+ Py_RETURN_RICHCOMPARE(result, 0, op);
}
static PyTypeObject kqueue_event_Type = {
diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c
index c92cfc01fd1..83c3549d50b 100644
--- a/Objects/bytearrayobject.c
+++ b/Objects/bytearrayobject.c
@@ -1012,8 +1012,6 @@ bytearray_richcompare(PyObject *self, PyObject *other, int op)
{
Py_ssize_t self_size, other_size;
Py_buffer self_bytes, other_bytes;
- PyObject *res;
- Py_ssize_t minsize;
int cmp, rc;
/* Bytes can be compared to anything that supports the (binary)
@@ -1049,38 +1047,25 @@ bytearray_richcompare(PyObject *self, PyObject *other, int op)
if (self_size != other_size && (op == Py_EQ || op == Py_NE)) {
/* Shortcut: if the lengths differ, the objects differ */
- cmp = (op == Py_NE);
+ PyBuffer_Release(&self_bytes);
+ PyBuffer_Release(&other_bytes);
+ return PyBool_FromLong((op == Py_NE));
}
else {
- minsize = self_size;
- if (other_size < minsize)
- minsize = other_size;
-
- cmp = memcmp(self_bytes.buf, other_bytes.buf, minsize);
+ cmp = memcmp(self_bytes.buf, other_bytes.buf,
+ Py_MIN(self_size, other_size));
/* In ISO C, memcmp() guarantees to use unsigned bytes! */
- if (cmp == 0) {
- if (self_size < other_size)
- cmp = -1;
- else if (self_size > other_size)
- cmp = 1;
- }
+ PyBuffer_Release(&self_bytes);
+ PyBuffer_Release(&other_bytes);
- switch (op) {
- case Py_LT: cmp = cmp < 0; break;
- case Py_LE: cmp = cmp <= 0; break;
- case Py_EQ: cmp = cmp == 0; break;
- case Py_NE: cmp = cmp != 0; break;
- case Py_GT: cmp = cmp > 0; break;
- case Py_GE: cmp = cmp >= 0; break;
+ if (cmp != 0) {
+ Py_RETURN_RICHCOMPARE(cmp, 0, op);
}
+
+ Py_RETURN_RICHCOMPARE(self_size, other_size, op);
}
- res = cmp ? Py_True : Py_False;
- PyBuffer_Release(&self_bytes);
- PyBuffer_Release(&other_bytes);
- Py_INCREF(res);
- return res;
}
static void
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index 7ba90aa307b..a921d9cb8c5 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -1566,7 +1566,6 @@ bytes_richcompare(PyBytesObject *a, PyBytesObject *b, int op)
int c;
Py_ssize_t len_a, len_b;
Py_ssize_t min_len;
- PyObject *result;
int rc;
/* Make sure both arguments are strings. */
@@ -1599,7 +1598,7 @@ bytes_richcompare(PyBytesObject *a, PyBytesObject *b, int op)
}
}
}
- result = Py_NotImplemented;
+ Py_RETURN_NOTIMPLEMENTED;
}
else if (a == b) {
switch (op) {
@@ -1607,12 +1606,12 @@ bytes_richcompare(PyBytesObject *a, PyBytesObject *b, int op)
case Py_LE:
case Py_GE:
/* a string is equal to itself */
- result = Py_True;
+ Py_RETURN_TRUE;
break;
case Py_NE:
case Py_LT:
case Py_GT:
- result = Py_False;
+ Py_RETURN_FALSE;
break;
default:
PyErr_BadArgument();
@@ -1622,7 +1621,7 @@ bytes_richcompare(PyBytesObject *a, PyBytesObject *b, int op)
else if (op == Py_EQ || op == Py_NE) {
int eq = bytes_compare_eq(a, b);
eq ^= (op == Py_NE);
- result = eq ? Py_True : Py_False;
+ return PyBool_FromLong(eq);
}
else {
len_a = Py_SIZE(a);
@@ -1635,22 +1634,10 @@ bytes_richcompare(PyBytesObject *a, PyBytesObject *b, int op)
}
else
c = 0;
- if (c == 0)
- c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0;
- switch (op) {
- case Py_LT: c = c < 0; break;
- case Py_LE: c = c <= 0; break;
- case Py_GT: c = c > 0; break;
- case Py_GE: c = c >= 0; break;
- default:
- PyErr_BadArgument();
- return NULL;
- }
- result = c ? Py_True : Py_False;
+ if (c != 0)
+ Py_RETURN_RICHCOMPARE(c, 0, op);
+ Py_RETURN_RICHCOMPARE(len_a, len_b, op);
}
-
- Py_INCREF(result);
- return result;
}
static Py_hash_t
diff --git a/Objects/cellobject.c b/Objects/cellobject.c
index af19229c4b6..7b05e61ce46 100644
--- a/Objects/cellobject.c
+++ b/Objects/cellobject.c
@@ -53,22 +53,15 @@ cell_dealloc(PyCellObject *op)
PyObject_GC_Del(op);
}
-#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
-
static PyObject *
cell_richcompare(PyObject *a, PyObject *b, int op)
{
- int result;
- PyObject *v;
-
/* neither argument should be NULL, unless something's gone wrong */
assert(a != NULL && b != NULL);
/* both arguments should be instances of PyCellObject */
if (!PyCell_Check(a) || !PyCell_Check(b)) {
- v = Py_NotImplemented;
- Py_INCREF(v);
- return v;
+ Py_RETURN_NOTIMPLEMENTED;
}
/* compare cells by contents; empty cells come before anything else */
@@ -77,32 +70,7 @@ cell_richcompare(PyObject *a, PyObject *b, int op)
if (a != NULL && b != NULL)
return PyObject_RichCompare(a, b, op);
- result = (b == NULL) - (a == NULL);
- switch (op) {
- case Py_EQ:
- v = TEST_COND(result == 0);
- break;
- case Py_NE:
- v = TEST_COND(result != 0);
- break;
- case Py_LE:
- v = TEST_COND(result <= 0);
- break;
- case Py_GE:
- v = TEST_COND(result >= 0);
- break;
- case Py_LT:
- v = TEST_COND(result < 0);
- break;
- case Py_GT:
- v = TEST_COND(result > 0);
- break;
- default:
- PyErr_BadArgument();
- return NULL;
- }
- Py_INCREF(v);
- return v;
+ Py_RETURN_RICHCOMPARE(b == NULL, a == NULL, op);
}
static PyObject *
diff --git a/Objects/descrobject.c b/Objects/descrobject.c
index 5dc27ef6727..71d522433a2 100644
--- a/Objects/descrobject.c
+++ b/Objects/descrobject.c
@@ -1035,22 +1035,16 @@ wrapper_dealloc(wrapperobject *wp)
Py_TRASHCAN_SAFE_END(wp)
}
-#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
-
static PyObject *
wrapper_richcompare(PyObject *a, PyObject *b, int op)
{
- intptr_t result;
- PyObject *v;
PyWrapperDescrObject *a_descr, *b_descr;
assert(a != NULL && b != NULL);
/* both arguments should be wrapperobjects */
if (!Wrapper_Check(a) || !Wrapper_Check(b)) {
- v = Py_NotImplemented;
- Py_INCREF(v);
- return v;
+ Py_RETURN_NOTIMPLEMENTED;
}
/* compare by descriptor address; if the descriptors are the same,
@@ -1063,32 +1057,7 @@ wrapper_richcompare(PyObject *a, PyObject *b, int op)
return PyObject_RichCompare(a, b, op);
}
- result = a_descr - b_descr;
- switch (op) {
- case Py_EQ:
- v = TEST_COND(result == 0);
- break;
- case Py_NE:
- v = TEST_COND(result != 0);
- break;
- case Py_LE:
- v = TEST_COND(result <= 0);
- break;
- case Py_GE:
- v = TEST_COND(result >= 0);
- break;
- case Py_LT:
- v = TEST_COND(result < 0);
- break;
- case Py_GT:
- v = TEST_COND(result > 0);
- break;
- default:
- PyErr_BadArgument();
- return NULL;
- }
- Py_INCREF(v);
- return v;
+ Py_RETURN_RICHCOMPARE(a_descr, b_descr, op);
}
static Py_hash_t
diff --git a/Objects/listobject.c b/Objects/listobject.c
index 858532252e9..7eba61e7fed 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -2330,13 +2330,10 @@ list_richcompare(PyObject *v, PyObject *w, int op)
if (Py_SIZE(vl) != Py_SIZE(wl) && (op == Py_EQ || op == Py_NE)) {
/* Shortcut: if the lengths differ, the lists differ */
- PyObject *res;
if (op == Py_EQ)
- res = Py_False;
+ Py_RETURN_FALSE;
else
- res = Py_True;
- Py_INCREF(res);
- return res;
+ Py_RETURN_TRUE;
}
/* Search for the first index where items are different */
@@ -2351,25 +2348,7 @@ list_richcompare(PyObject *v, PyObject *w, int op)
if (i >= Py_SIZE(vl) || i >= Py_SIZE(wl)) {
/* No more items to compare -- compare sizes */
- Py_ssize_t vs = Py_SIZE(vl);
- Py_ssize_t ws = Py_SIZE(wl);
- int cmp;
- PyObject *res;
- switch (op) {
- case Py_LT: cmp = vs < ws; break;
- case Py_LE: cmp = vs <= ws; break;
- case Py_EQ: cmp = vs == ws; break;
- case Py_NE: cmp = vs != ws; break;
- case Py_GT: cmp = vs > ws; break;
- case Py_GE: cmp = vs >= ws; break;
- default: return NULL; /* cannot happen */
- }
- if (cmp)
- res = Py_True;
- else
- res = Py_False;
- Py_INCREF(res);
- return res;
+ Py_RETURN_RICHCOMPARE(Py_SIZE(vl), Py_SIZE(wl), op);
}
/* We have an item that differs -- shortcuts for EQ/NE */
diff --git a/Objects/longobject.c b/Objects/longobject.c
index c71b783cc03..6fd4feba12a 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -2915,45 +2915,16 @@ long_compare(PyLongObject *a, PyLongObject *b)
return sign < 0 ? -1 : sign > 0 ? 1 : 0;
}
-#define TEST_COND(cond) \
- ((cond) ? Py_True : Py_False)
-
static PyObject *
long_richcompare(PyObject *self, PyObject *other, int op)
{
int result;
- PyObject *v;
CHECK_BINOP(self, other);
if (self == other)
result = 0;
else
result = long_compare((PyLongObject*)self, (PyLongObject*)other);
- /* Convert the return value to a Boolean */
- switch (op) {
- case Py_EQ:
- v = TEST_COND(result == 0);
- break;
- case Py_NE:
- v = TEST_COND(result != 0);
- break;
- case Py_LE:
- v = TEST_COND(result <= 0);
- break;
- case Py_GE:
- v = TEST_COND(result >= 0);
- break;
- case Py_LT:
- v = TEST_COND(result == -1);
- break;
- case Py_GT:
- v = TEST_COND(result == 1);
- break;
- default:
- PyErr_BadArgument();
- return NULL;
- }
- Py_INCREF(v);
- return v;
+ Py_RETURN_RICHCOMPARE(result, 0, op);
}
static Py_hash_t
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c
index c150af8ed1a..35decd8bb80 100644
--- a/Objects/tupleobject.c
+++ b/Objects/tupleobject.c
@@ -647,23 +647,7 @@ tuplerichcompare(PyObject *v, PyObject *w, int op)
if (i >= vlen || i >= wlen) {
/* No more items to compare -- compare sizes */
- int cmp;
- PyObject *res;
- switch (op) {
- case Py_LT: cmp = vlen < wlen; break;
- case Py_LE: cmp = vlen <= wlen; break;
- case Py_EQ: cmp = vlen == wlen; break;
- case Py_NE: cmp = vlen != wlen; break;
- case Py_GT: cmp = vlen > wlen; break;
- case Py_GE: cmp = vlen >= wlen; break;
- default: return NULL; /* cannot happen */
- }
- if (cmp)
- res = Py_True;
- else
- res = Py_False;
- Py_INCREF(res);
- return res;
+ Py_RETURN_RICHCOMPARE(vlen, wlen, op);
}
/* We have an item that differs -- shortcuts for EQ/NE */
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 6533f4142b5..194c5bcdcf1 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -11152,14 +11152,10 @@ _PyUnicode_EqualToASCIIId(PyObject *left, _Py_Identifier *right)
return unicode_compare_eq(left, right_uni);
}
-#define TEST_COND(cond) \
- ((cond) ? Py_True : Py_False)
-
PyObject *
PyUnicode_RichCompare(PyObject *left, PyObject *right, int op)
{
int result;
- PyObject *v;
if (!PyUnicode_Check(left) || !PyUnicode_Check(right))
Py_RETURN_NOTIMPLEMENTED;
@@ -11174,13 +11170,11 @@ PyUnicode_RichCompare(PyObject *left, PyObject *right, int op)
case Py_LE:
case Py_GE:
/* a string is equal to itself */
- v = Py_True;
- break;
+ Py_RETURN_TRUE;
case Py_NE:
case Py_LT:
case Py_GT:
- v = Py_False;
- break;
+ Py_RETURN_FALSE;
default:
PyErr_BadArgument();
return NULL;
@@ -11189,32 +11183,12 @@ PyUnicode_RichCompare(PyObject *left, PyObject *right, int op)
else if (op == Py_EQ || op == Py_NE) {
result = unicode_compare_eq(left, right);
result ^= (op == Py_NE);
- v = TEST_COND(result);
+ return PyBool_FromLong(result);
}
else {
result = unicode_compare(left, right);
-
- /* Convert the return value to a Boolean */
- switch (op) {
- case Py_LE:
- v = TEST_COND(result <= 0);
- break;
- case Py_GE:
- v = TEST_COND(result >= 0);
- break;
- case Py_LT:
- v = TEST_COND(result == -1);
- break;
- case Py_GT:
- v = TEST_COND(result == 1);
- break;
- default:
- PyErr_BadArgument();
- return NULL;
- }
+ Py_RETURN_RICHCOMPARE(result, 0, op);
}
- Py_INCREF(v);
- return v;
}
int
1
0
results for 4243df51fe43 on branch "default"
--------------------------------------------
test_collections leaked [-7, 1, 0] memory blocks, sum=-6
test_functools leaked [0, 3, 1] memory blocks, sum=4
test_multiprocessing_forkserver leaked [-2, 1, -1] memory blocks, sum=-2
Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogQpQ4_S', '--timeout', '7200']
1
0
[6 down, 59 flat] Results for Python (master branch) 2017-11-01
by lp_benchmark_robot@intel.com Nov. 1, 2017
by lp_benchmark_robot@intel.com Nov. 1, 2017
Nov. 1, 2017
Results for project python/master, build date: 2017-11-01 03:03:03-07:00.
- commit: 280c22a
- previous commit: f0f62cc
- revision date: 2017-10-31 19:48:14-07:00
- environment: Broadwell-EP
- cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores,
stepping 1, LLC 55 MB
- mem: 128 GB
- os: Ubuntu 16.04.2 LTS
- kernel: 4.4.0-62-generic x86_64 GNU/Linux
Baseline results were generated using release v3.6.0, with hash 5c4568a from
2016-12-22 23:38:47+00:00.
+-----+------------------------+--------+------------+------------+------------+
| | |relative|change since|change since|current rev |
| | benchmark|std_dev*| last run | baseline |run with PGO|
+-----+------------------------+--------+------------+------------+------------+
| :-| | 2to3| 0.953% | -0.910% | +3.583% | +8.189% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | call_method| 3.689% | +3.910% | +25.353% | +5.730% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | call_method_slots| 2.370% | +2.180% | +25.431% | +6.586% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | call_method_unknown| 1.981% | +2.796% | +24.538% | +5.687% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | call_simple| 2.724% | -3.666% | +5.607% | +10.901% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | chameleon| 2.126% | -1.693% | +10.232% | +9.904% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | chaos| 0.733% | -1.879% | +5.706% | +12.045% |
+-----+------------------------+--------+------------+------------+------------+
| :-( | crypto_pyaes| 0.578% | -4.653% | -0.299% | +10.163% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | deltablue| 4.289% | +0.421% | +7.703% | +19.151% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | django_template| 3.251% | +2.209% | +9.069% | +6.439% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | dulwich_log| 1.266% | +0.056% | +3.360% | +7.955% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | fannkuch| 0.555% | -0.699% | +2.836% | +7.547% |
+-----+------------------------+--------+------------+------------+------------+
| :-( | float| 0.919% | -3.940% | -0.754% | +9.786% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | genshi_text| 1.661% | -0.936% | +12.377% | +8.834% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | genshi_xml| 1.234% | +1.383% | +8.897% | +9.502% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | go| 0.974% | -0.792% | +4.064% | +13.631% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | hexiom| 1.556% | +0.373% | +10.105% | +12.019% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | html5lib| 2.808% | -0.516% | +7.749% | +8.601% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | json_dumps| 1.826% | -1.370% | +1.909% | +9.243% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | json_loads| 1.076% | +2.381% | +1.973% | +11.960% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | logging_format| 1.521% | +0.979% | +8.642% | +10.906% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | logging_silent| 2.611% | +0.268% | +47.246% | +11.279% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | logging_simple| 1.586% | +0.432% | +8.673% | +12.433% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | mako| 0.670% | +0.325% | +17.331% | +12.930% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | mdp| 2.780% | -2.049% | +7.382% | +9.887% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | meteor_contest| 3.895% | +2.468% | +5.389% | +3.897% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | nbody| 0.678% | -0.528% | -0.686% | -1.133% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | nqueens| 2.789% | -4.276% | +2.944% | +9.330% |
+-----+------------------------+--------+------------+------------+------------+
| :-( | pathlib| 1.108% | -3.275% | +3.688% | +11.426% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | pickle| 1.143% | +2.031% | +1.145% | +22.013% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | pickle_dict| 0.627% | -0.187% | +1.106% | +24.343% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | pickle_list| 0.900% | -0.121% | +4.459% | +19.524% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | pickle_pure_python| 2.960% | +0.105% | +10.924% | +10.408% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | pidigits| 0.134% | +0.237% | +0.305% | +9.826% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | python_startup| 0.120% | -0.341% | +10.773% | +4.886% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | python_startup_no_site| 0.093% | -0.512% | +1.907% | +5.253% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | raytrace| 1.446% | -0.064% | +9.211% | +12.580% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | regex_compile| 5.550% | +4.609% | +3.059% | +7.540% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | regex_dna| 1.288% | +1.704% | +0.134% | +9.238% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | regex_effbot| 2.150% | -1.095% | -3.855% | +2.505% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | regex_v8| 1.785% | -0.818% | +5.230% | +4.731% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | richards| 1.517% | -1.202% | +5.843% | +16.269% |
+-----+------------------------+--------+------------+------------+------------+
| :-( | scimark_fft| 0.524% | -5.612% | -2.940% | +5.940% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | scimark_lu| 3.144% | -0.833% | +27.150% | +8.896% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | scimark_monte_carlo| 2.130% | -2.208% | +1.925% | +8.293% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | scimark_sor| 0.562% | -1.357% | +14.403% | +9.270% |
+-----+------------------------+--------+------------+------------+------------+
| :-( | scimark_sparse_mat_mult| 0.925% | -3.546% | +0.685% | +2.521% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | spectral_norm| 0.494% | -1.792% | +5.240% | +4.518% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | sqlalchemy_declarative| 1.078% | -0.173% | +6.068% | +5.942% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | sqlalchemy_imperative| 3.383% | -0.088% | +6.127% | +3.376% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | sqlite_synth| 4.606% | -0.439% | +17.350% | +9.307% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | sympy_expand| 2.268% | +0.669% | +11.335% | +7.067% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | sympy_integrate| 2.105% | -0.251% | +8.636% | +7.079% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | sympy_str| 4.154% | +0.977% | +11.019% | +8.947% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | sympy_sum| 5.104% | +0.330% | +10.312% | +9.788% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | telco| 3.490% | -2.396% | +20.934% | +13.076% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | tornado_http| 1.076% | +0.330% | +5.661% | +6.539% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | unpack_sequence| 0.765% | +0.252% | +2.397% | +1.190% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | unpickle| 7.175% | -2.964% | +8.119% | +18.254% |
+-----+------------------------+--------+------------+------------+------------+
| :-( | unpickle_list| 2.971% | -4.795% | +0.418% | +18.701% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | unpickle_pure_python| 2.898% | -0.398% | +7.534% | +6.150% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | xml_etree_generate| 1.617% | -0.546% | +5.865% | +8.318% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | xml_etree_iterparse| 1.977% | +0.938% | +3.905% | +5.989% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | xml_etree_parse| 3.137% | +0.818% | -4.792% | +11.042% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | xml_etree_process| 1.541% | -1.091% | +6.654% | +8.940% |
+-----+------------------------+--------+------------+------------+------------+
* Relative Standard Deviation (Standard Deviation/Average)
If this is not displayed properly please visit our results page here:
http://languagesperformance.intel.com/6-down-59-flat-results-for-python-mas…
Our lab does a nightly source pull and build of the Python project and measures
performance changes against the previous stable version and the previous nightly
measurement. This is provided as a service to the community so that quality
issues with current hardware can be identified quickly.
Intel technologies' features and benefits depend on system configuration and may
require enabled hardware, software or service activation. Performance varies
depending on system configuration.
1
0
bpo-27666: Fixed stack corruption in curses.box() and curses.ungetmouse(). (GH-4220) (#4221)
by Serhiy Storchaka Nov. 1, 2017
by Serhiy Storchaka Nov. 1, 2017
Nov. 1, 2017
https://github.com/python/cpython/commit/aad7ac10af6ed40fc21b842e04be0b04b2…
commit: aad7ac10af6ed40fc21b842e04be0b04b2915d4a
branch: 3.6
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: Serhiy Storchaka <storchaka(a)gmail.com>
date: 2017-11-01T21:23:46+02:00
summary:
bpo-27666: Fixed stack corruption in curses.box() and curses.ungetmouse(). (GH-4220) (#4221)
(cherry picked from commit 4f469c096628af730b17798d0ebfd8925bfde836)
files:
A Misc/NEWS.d/next/Library/2017-11-01-18-13-42.bpo-27666.j2zRnF.rst
M Lib/test/test_curses.py
M Modules/_cursesmodule.c
diff --git a/Lib/test/test_curses.py b/Lib/test/test_curses.py
index 8bb6630284d..17b3af47c35 100644
--- a/Lib/test/test_curses.py
+++ b/Lib/test/test_curses.py
@@ -92,7 +92,7 @@ def test_window_funcs(self):
with self.subTest(meth=meth.__qualname__, args=args):
meth(*args)
- for meth in [stdscr.box, stdscr.clear, stdscr.clrtobot,
+ for meth in [stdscr.clear, stdscr.clrtobot,
stdscr.clrtoeol, stdscr.cursyncup, stdscr.delch,
stdscr.deleteln, stdscr.erase, stdscr.getbegyx,
stdscr.getbkgd, stdscr.getkey, stdscr.getmaxyx,
@@ -126,6 +126,13 @@ def test_window_funcs(self):
win.border(65, 66, 67, 68,
69, [], 71, 72)
+ win.box(65, 67)
+ win.box('!', '_')
+ win.box(b':', b'~')
+ self.assertRaises(TypeError, win.box, 65, 66, 67)
+ self.assertRaises(TypeError, win.box, 65)
+ win.box()
+
stdscr.clearok(1)
win4 = stdscr.derwin(2,2)
diff --git a/Misc/NEWS.d/next/Library/2017-11-01-18-13-42.bpo-27666.j2zRnF.rst b/Misc/NEWS.d/next/Library/2017-11-01-18-13-42.bpo-27666.j2zRnF.rst
new file mode 100644
index 00000000000..a74f0adfa16
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2017-11-01-18-13-42.bpo-27666.j2zRnF.rst
@@ -0,0 +1,3 @@
+Fixed stack corruption in curses.box() and curses.ungetmouse() when the size
+of types chtype or mmask_t is less than the size of C long. curses.box()
+now accepts characters as arguments. Based on patch by Steve Fink.
diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c
index 0e4cd536a31..9a691dbe714 100644
--- a/Modules/_cursesmodule.c
+++ b/Modules/_cursesmodule.c
@@ -912,12 +912,19 @@ PyCursesWindow_Border(PyCursesWindowObject *self, PyObject *args)
static PyObject *
PyCursesWindow_Box(PyCursesWindowObject *self, PyObject *args)
{
+ PyObject *temp1, *temp2;
chtype ch1=0,ch2=0;
switch(PyTuple_Size(args)){
case 0: break;
default:
- if (!PyArg_ParseTuple(args,"ll;vertint,horint", &ch1, &ch2))
+ if (!PyArg_ParseTuple(args,"OO;verch,horch", &temp1, &temp2))
return NULL;
+ if (!PyCurses_ConvertToChtype(self, temp1, &ch1)) {
+ return NULL;
+ }
+ if (!PyCurses_ConvertToChtype(self, temp2, &ch2)) {
+ return NULL;
+ }
}
box(self->win,ch1,ch2);
Py_INCREF(Py_None);
@@ -2285,24 +2292,30 @@ PyCurses_GetMouse(PyObject *self)
PyErr_SetString(PyCursesError, "getmouse() returned ERR");
return NULL;
}
- return Py_BuildValue("(hiiil)",
+ return Py_BuildValue("(hiiik)",
(short)event.id,
- event.x, event.y, event.z,
- (long) event.bstate);
+ (int)event.x, (int)event.y, (int)event.z,
+ (unsigned long) event.bstate);
}
static PyObject *
PyCurses_UngetMouse(PyObject *self, PyObject *args)
{
MEVENT event;
+ short id;
+ int x, y, z;
+ unsigned long bstate;
PyCursesInitialised;
- if (!PyArg_ParseTuple(args, "hiiil",
- &event.id,
- &event.x, &event.y, &event.z,
- (int *) &event.bstate))
+ if (!PyArg_ParseTuple(args, "hiiik",
+ &id, &x, &y, &z, &bstate))
return NULL;
+ event.id = id;
+ event.x = x;
+ event.y = y;
+ event.z = z;
+ event.bstate = bstate;
return PyCursesCheckERR(ungetmouse(&event), "ungetmouse");
}
#endif
@@ -2701,14 +2714,15 @@ PyCurses_MouseInterval(PyObject *self, PyObject *args)
static PyObject *
PyCurses_MouseMask(PyObject *self, PyObject *args)
{
- int newmask;
+ unsigned long newmask;
mmask_t oldmask, availmask;
PyCursesInitialised;
- if (!PyArg_ParseTuple(args,"i;mousemask",&newmask))
+ if (!PyArg_ParseTuple(args,"k;mousemask",&newmask))
return NULL;
- availmask = mousemask(newmask, &oldmask);
- return Py_BuildValue("(ll)", (long)availmask, (long)oldmask);
+ availmask = mousemask((mmask_t)newmask, &oldmask);
+ return Py_BuildValue("(kk)",
+ (unsigned long)availmask, (unsigned long)oldmask);
}
#endif
1
0
bpo-27666: Fixed stack corruption in curses.box() and curses.ungetmouse(). (GH-4220) (#4222)
by Serhiy Storchaka Nov. 1, 2017
by Serhiy Storchaka Nov. 1, 2017
Nov. 1, 2017
https://github.com/python/cpython/commit/b694770a2b23cd485c98bf673a8b2dc1a8…
commit: b694770a2b23cd485c98bf673a8b2dc1a865d9df
branch: 2.7
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: Serhiy Storchaka <storchaka(a)gmail.com>
date: 2017-11-01T21:24:00+02:00
summary:
bpo-27666: Fixed stack corruption in curses.box() and curses.ungetmouse(). (GH-4220) (#4222)
(cherry picked from commit 4f469c096628af730b17798d0ebfd8925bfde836)
files:
A Misc/NEWS.d/next/Library/2017-11-01-18-13-42.bpo-27666.j2zRnF.rst
M Lib/test/test_curses.py
M Modules/_cursesmodule.c
diff --git a/Lib/test/test_curses.py b/Lib/test/test_curses.py
index 6d3ab7c0400..502c2228a5f 100644
--- a/Lib/test/test_curses.py
+++ b/Lib/test/test_curses.py
@@ -92,7 +92,7 @@ def test_window_funcs(self):
(4,4, 'a'), (5,5, 'a', curses.A_BOLD)]:
meth(*args)
- for meth in [stdscr.box, stdscr.clear, stdscr.clrtobot,
+ for meth in [stdscr.clear, stdscr.clrtobot,
stdscr.clrtoeol, stdscr.cursyncup, stdscr.delch,
stdscr.deleteln, stdscr.erase, stdscr.getbegyx,
stdscr.getbkgd, stdscr.getkey, stdscr.getmaxyx,
@@ -125,6 +125,13 @@ def test_window_funcs(self):
win.border(65, 66, 67, 68,
69, [], 71, 72)
+ win.box(65, 67)
+ win.box('!', '_')
+ win.box(b':', b'~')
+ self.assertRaises(TypeError, win.box, 65, 66, 67)
+ self.assertRaises(TypeError, win.box, 65)
+ win.box()
+
stdscr.clearok(1)
win4 = stdscr.derwin(2,2)
diff --git a/Misc/NEWS.d/next/Library/2017-11-01-18-13-42.bpo-27666.j2zRnF.rst b/Misc/NEWS.d/next/Library/2017-11-01-18-13-42.bpo-27666.j2zRnF.rst
new file mode 100644
index 00000000000..a74f0adfa16
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2017-11-01-18-13-42.bpo-27666.j2zRnF.rst
@@ -0,0 +1,3 @@
+Fixed stack corruption in curses.box() and curses.ungetmouse() when the size
+of types chtype or mmask_t is less than the size of C long. curses.box()
+now accepts characters as arguments. Based on patch by Steve Fink.
diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c
index 75b19892efc..c3d4230ebd5 100644
--- a/Modules/_cursesmodule.c
+++ b/Modules/_cursesmodule.c
@@ -639,12 +639,19 @@ PyCursesWindow_Border(PyCursesWindowObject *self, PyObject *args)
static PyObject *
PyCursesWindow_Box(PyCursesWindowObject *self, PyObject *args)
{
+ PyObject *temp1, *temp2;
chtype ch1=0,ch2=0;
switch(PyTuple_Size(args)){
case 0: break;
default:
- if (!PyArg_ParseTuple(args,"ll;vertint,horint", &ch1, &ch2))
+ if (!PyArg_ParseTuple(args,"OO;verch,horch", &temp1, &temp2))
return NULL;
+ if (!PyCurses_ConvertToChtype(self, temp1, &ch1)) {
+ return NULL;
+ }
+ if (!PyCurses_ConvertToChtype(self, temp2, &ch2)) {
+ return NULL;
+ }
}
box(self->win,ch1,ch2);
Py_INCREF(Py_None);
@@ -1826,24 +1833,30 @@ PyCurses_GetMouse(PyObject *self)
PyErr_SetString(PyCursesError, "getmouse() returned ERR");
return NULL;
}
- return Py_BuildValue("(hiiil)",
+ return Py_BuildValue("(hiiik)",
(short)event.id,
- event.x, event.y, event.z,
- (long) event.bstate);
+ (int)event.x, (int)event.y, (int)event.z,
+ (unsigned long) event.bstate);
}
static PyObject *
PyCurses_UngetMouse(PyObject *self, PyObject *args)
{
MEVENT event;
+ short id;
+ int x, y, z;
+ unsigned long bstate;
PyCursesInitialised;
- if (!PyArg_ParseTuple(args, "hiiil",
- &event.id,
- &event.x, &event.y, &event.z,
- (int *) &event.bstate))
+ if (!PyArg_ParseTuple(args, "hiiik",
+ &id, &x, &y, &z, &bstate))
return NULL;
+ event.id = id;
+ event.x = x;
+ event.y = y;
+ event.z = z;
+ event.bstate = bstate;
return PyCursesCheckERR(ungetmouse(&event), "ungetmouse");
}
#endif
@@ -2200,14 +2213,15 @@ PyCurses_MouseInterval(PyObject *self, PyObject *args)
static PyObject *
PyCurses_MouseMask(PyObject *self, PyObject *args)
{
- int newmask;
+ unsigned long newmask;
mmask_t oldmask, availmask;
PyCursesInitialised;
- if (!PyArg_ParseTuple(args,"i;mousemask",&newmask))
+ if (!PyArg_ParseTuple(args,"k;mousemask",&newmask))
return NULL;
- availmask = mousemask(newmask, &oldmask);
- return Py_BuildValue("(ll)", (long)availmask, (long)oldmask);
+ availmask = mousemask((mmask_t)newmask, &oldmask);
+ return Py_BuildValue("(kk)",
+ (unsigned long)availmask, (unsigned long)oldmask);
}
#endif
1
0