From 12695f4c6d1167c0863098a586f3dfeb77a7cb9a Mon Sep 17 00:00:00 2001 From: Mathieu Dupuy Date: Thu, 20 Aug 2020 22:08:37 +0200 Subject: [PATCH 01/63] Doc: add a missing period (GH-21819) --- Doc/library/json.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/json.rst b/Doc/library/json.rst index b923c8e1670529..e1a246aad6190b 100644 --- a/Doc/library/json.rst +++ b/Doc/library/json.rst @@ -745,7 +745,7 @@ Command line options .. cmdoption:: --indent, --tab, --no-indent, --compact - Mutually exclusive options for whitespace control + Mutually exclusive options for whitespace control. .. versionadded:: 3.9 From d2b0ce6c35dc18d3f81b1fa73579d2f65fbc85af Mon Sep 17 00:00:00 2001 From: "Ernest W. Durbin III" Date: Fri, 21 Aug 2020 17:34:06 -0400 Subject: [PATCH 02/63] Update references from travis-ci.org to travis-ci.com (GH-21919) --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 96c9561e7c8eb1..9a646a2ee5da2d 100644 --- a/README.rst +++ b/README.rst @@ -1,9 +1,9 @@ This is Python version 3.10.0 alpha 0 ===================================== -.. image:: https://travis-ci.org/python/cpython.svg?branch=master +.. image:: https://travis-ci.com/python/cpython.svg?branch=master :alt: CPython build status on Travis CI - :target: https://travis-ci.org/python/cpython + :target: https://travis-ci.com/python/cpython .. image:: https://github.com/python/cpython/workflows/Tests/badge.svg :alt: CPython build status on GitHub Actions From 7173fc84e61b80b19261e47fca38030206a3a78e Mon Sep 17 00:00:00 2001 From: wyz23x2 <52805709+wyz23x2@users.noreply.github.com> Date: Sat, 22 Aug 2020 06:28:54 +0800 Subject: [PATCH 03/63] bpo-41573: Update release versions in General FAQ (GH-21915) --- Doc/faq/general.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/faq/general.rst b/Doc/faq/general.rst index eee3c3c203efa5..cf70f16c6fe328 100644 --- a/Doc/faq/general.rst +++ b/Doc/faq/general.rst @@ -142,9 +142,9 @@ to fix critical bugs. Alpha, beta and release candidate versions have an additional suffix. The suffix for an alpha version is "aN" for some small number N, the suffix for a beta version is "bN" for some small number N, and the suffix for a release -candidate version is "cN" for some small number N. In other words, all versions +candidate version is "rcN" for some small number N. In other words, all versions labeled 2.0aN precede the versions labeled 2.0bN, which precede versions labeled -2.0cN, and *those* precede 2.0. +2.0rcN, and *those* precede 2.0. You may also find version numbers with a "+" suffix, e.g. "2.2+". These are unreleased versions, built directly from the CPython development repository. In @@ -309,8 +309,8 @@ releases. The latest stable releases can always be found on the `Python download page `_. There are two production-ready versions of Python: 2.x and 3.x. The recommended version is 3.x, which is supported by -most widely used libraries. Although 2.x is still widely used, `it will not -be maintained after January 1, 2020 `_. +most widely used libraries. Although 2.x is still widely used, `it is not +maintained anymore `_. How many people are using Python? --------------------------------- From 802726acf6048338394a6a4750835c2cdd6a947b Mon Sep 17 00:00:00 2001 From: Andre Delfino Date: Fri, 21 Aug 2020 19:29:34 -0300 Subject: [PATCH 04/63] Document vars behavior when __dict__ is missing (#21466) --- Doc/library/functions.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 43c47c1da9434c..d381d43d8e99c3 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1734,6 +1734,9 @@ are always available. They are listed here in alphabetical order. locals dictionary is only useful for reads since updates to the locals dictionary are ignored. + A :exc:`TypeError` exception is raised if an object is specified but + it doesn't have a :attr:`~object.__dict__` attribute (for example, if + its class defines the :attr:`~object.__slots__` attribute). .. function:: zip(*iterables, strict=False) From 3112aab31426f19a939f10cf114ff4137ce96624 Mon Sep 17 00:00:00 2001 From: Will Binns Date: Mon, 24 Aug 2020 17:00:12 +0200 Subject: [PATCH 05/63] README: Add link to LICENSE (GH-21565) Thanks @wbnns for your contribution. --- README.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 9a646a2ee5da2d..14f4f32bca7965 100644 --- a/README.rst +++ b/README.rst @@ -259,8 +259,9 @@ rights reserved. Copyright (c) 1991-1995 Stichting Mathematisch Centrum. All rights reserved. -See the file "LICENSE" for information on the history of this software, terms & -conditions for usage, and a DISCLAIMER OF ALL WARRANTIES. +See the `LICENSE `_ for +information on the history of this software, terms & conditions for usage, and a +DISCLAIMER OF ALL WARRANTIES. This Python distribution contains *no* GNU General Public License (GPL) code, so it may be used in proprietary projects. There are interfaces to some GNU From 8e19c8be87017f6bef8e4c936b1e6ddacb558ad2 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Mon, 24 Aug 2020 17:40:08 -0700 Subject: [PATCH 06/63] bpo-41513: More accurate hypot() (GH-21916) --- .../2020-08-23-14-23-18.bpo-41513.DGqc_I.rst | 3 + Modules/mathmodule.c | 148 +++++++++++++----- 2 files changed, 114 insertions(+), 37 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2020-08-23-14-23-18.bpo-41513.DGqc_I.rst diff --git a/Misc/NEWS.d/next/Library/2020-08-23-14-23-18.bpo-41513.DGqc_I.rst b/Misc/NEWS.d/next/Library/2020-08-23-14-23-18.bpo-41513.DGqc_I.rst new file mode 100644 index 00000000000000..b4d0d9b63cf87d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-08-23-14-23-18.bpo-41513.DGqc_I.rst @@ -0,0 +1,3 @@ +Improved the accuracy of math.hypot(). Internally, each step is computed +with extra precision so that the result is now almost always correctly +rounded. diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 489802cc367450..1d6174132814b2 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -2404,52 +2404,79 @@ math_fmod_impl(PyObject *module, double x, double y) } /* -Given an *n* length *vec* of values and a value *max*, compute: +Given a *vec* of values, compute the vector norm: - sqrt(sum((x * scale) ** 2 for x in vec)) / scale + sqrt(sum(x ** 2 for x in vec)) - where scale is the first power of two - greater than max. - -or compute: - - max * sqrt(sum((x / max) ** 2 for x in vec)) - -The value of the *max* variable must be non-negative and -equal to the absolute value of the largest magnitude -entry in the vector. If n==0, then *max* should be 0.0. +The *max* variable should be equal to the largest fabs(x). +The *n* variable is the length of *vec*. +If n==0, then *max* should be 0.0. If an infinity is present in the vec, *max* should be INF. - The *found_nan* variable indicates whether some member of the *vec* is a NaN. -To improve accuracy and to increase the number of cases where -vector_norm() is commutative, we use a variant of Neumaier -summation specialized to exploit that we always know that -|csum| >= |x|. - -The *csum* variable tracks the cumulative sum and *frac* tracks -the cumulative fractional errors at each step. Since this -variant assumes that |csum| >= |x| at each step, we establish -the precondition by starting the accumulation from 1.0 which -represents the largest possible value of (x*scale)**2 or (x/max)**2. - -After the loop is finished, the initial 1.0 is subtracted out -for a net zero effect on the final sum. Since *csum* will be -greater than 1.0, the subtraction of 1.0 will not cause -fractional digits to be dropped from *csum*. - -To get the full benefit from compensated summation, the -largest addend should be in the range: 0.5 <= x <= 1.0. -Accordingly, scaling or division by *max* should not be skipped -even if not otherwise needed to prevent overflow or loss of precision. +To avoid overflow/underflow and to achieve high accuracy giving results +that are almost always correctly rounded, four techniques are used: + +* lossless scaling using a power-of-two scaling factor +* accurate squaring using Veltkamp-Dekker splitting +* compensated summation using a variant of the Neumaier algorithm +* differential correction of the square root + +The usual presentation of the Neumaier summation algorithm has an +expensive branch depending on which operand has the larger +magnitude. We avoid this cost by arranging the calculation so that +fabs(csum) is always as large as fabs(x). + +To establish the invariant, *csum* is initialized to 1.0 which is +always larger than x**2 after scaling or division by *max*. +After the loop is finished, the initial 1.0 is subtracted out for a +net zero effect on the final sum. Since *csum* will be greater than +1.0, the subtraction of 1.0 will not cause fractional digits to be +dropped from *csum*. + +To get the full benefit from compensated summation, the largest +addend should be in the range: 0.5 <= |x| <= 1.0. Accordingly, +scaling or division by *max* should not be skipped even if not +otherwise needed to prevent overflow or loss of precision. + +The assertion that hi*hi >= 1.0 is a bit subtle. Each vector element +gets scaled to a magnitude below 1.0. The Veltkamp-Dekker splitting +algorithm gives a *hi* value that is correctly rounded to half +precision. When a value at or below 1.0 is correctly rounded, it +never goes above 1.0. And when values at or below 1.0 are squared, +they remain at or below 1.0, thus preserving the summation invariant. + +The square root differential correction is needed because a +correctly rounded square root of a correctly rounded sum of +squares can still be off by as much as one ulp. + +The differential correction starts with a value *x* that is +the difference between the square of *h*, the possibly inaccurately +rounded square root, and the accurately computed sum of squares. +The correction is the first order term of the Maclaurin series +expansion of sqrt(h**2 + x) == h + x/(2*h) + O(x**2). + +Essentially, this differential correction is equivalent to one +refinement step in the Newton divide-and-average square root +algorithm, effectively doubling the number of accurate bits. +This technique is used in Dekker's SQRT2 algorithm and again in +Borges' ALGORITHM 4 and 5. + +References: + +1. Veltkamp-Dekker splitting: http://csclub.uwaterloo.ca/~pbarfuss/dekker1971.pdf +2. Compensated summation: http://www.ti3.tu-harburg.de/paper/rump/Ru08b.pdf +3. Square root diffential correction: https://arxiv.org/pdf/1904.09481.pdf */ static inline double vector_norm(Py_ssize_t n, double *vec, double max, int found_nan) { + const double T27 = 134217729.0; /* ldexp(1.0, 27)+1.0) */ double x, csum = 1.0, oldcsum, frac = 0.0, scale; + double t, hi, lo, h; int max_e; Py_ssize_t i; @@ -2470,15 +2497,62 @@ vector_norm(Py_ssize_t n, double *vec, double max, int found_nan) for (i=0 ; i < n ; i++) { x = vec[i]; assert(Py_IS_FINITE(x) && fabs(x) <= max); + x *= scale; - x = x*x; + assert(fabs(x) < 1.0); + + t = x * T27; + hi = t - (t - x); + lo = x - hi; + assert(hi + lo == x); + + x = hi * hi; assert(x <= 1.0); - assert(csum >= x); + assert(fabs(csum) >= fabs(x)); + oldcsum = csum; + csum += x; + frac += (oldcsum - csum) + x; + + x = 2.0 * hi * lo; + assert(fabs(csum) >= fabs(x)); + oldcsum = csum; + csum += x; + frac += (oldcsum - csum) + x; + + x = lo * lo; + assert(fabs(csum) >= fabs(x)); oldcsum = csum; csum += x; frac += (oldcsum - csum) + x; } - return sqrt(csum - 1.0 + frac) / scale; + h = sqrt(csum - 1.0 + frac); + + x = h; + t = x * T27; + hi = t - (t - x); + lo = x - hi; + assert (hi + lo == x); + + x = -hi * hi; + assert(fabs(csum) >= fabs(x)); + oldcsum = csum; + csum += x; + frac += (oldcsum - csum) + x; + + x = -2.0 * hi * lo; + assert(fabs(csum) >= fabs(x)); + oldcsum = csum; + csum += x; + frac += (oldcsum - csum) + x; + + x = -lo * lo; + assert(fabs(csum) >= fabs(x)); + oldcsum = csum; + csum += x; + frac += (oldcsum - csum) + x; + + x = csum - 1.0 + frac; + return (h + x / (2.0 * h)) / scale; } /* When max_e < -1023, ldexp(1.0, -max_e) overflows. So instead of multiplying by a scale, we just divide by *max*. @@ -2489,7 +2563,7 @@ vector_norm(Py_ssize_t n, double *vec, double max, int found_nan) x /= max; x = x*x; assert(x <= 1.0); - assert(csum >= x); + assert(fabs(csum) >= fabs(x)); oldcsum = csum; csum += x; frac += (oldcsum - csum) + x; From c517fc712105c8e5930cb42baaebdbe37fc3e15f Mon Sep 17 00:00:00 2001 From: Elvis Pranskevichus Date: Wed, 26 Aug 2020 09:42:22 -0700 Subject: [PATCH 07/63] bpo-32751: Wait for task cancel in asyncio.wait_for() when timeout <= 0 (#21895) When I was fixing bpo-32751 back in GH-7216 I missed the case when *timeout* is zero or negative. This takes care of that. Props to @aaliddell for noticing the inconsistency. --- Lib/asyncio/tasks.py | 9 ++++-- Lib/test/test_asyncio/test_tasks.py | 31 +++++++++++++++++++ .../2020-08-15-15-50-12.bpo-32751.85je5X.rst | 3 ++ 3 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2020-08-15-15-50-12.bpo-32751.85je5X.rst diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index c37f0e1387980c..7ecec9638489df 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -445,8 +445,13 @@ async def wait_for(fut, timeout, *, loop=None): if fut.done(): return fut.result() - fut.cancel() - raise exceptions.TimeoutError() + await _cancel_and_wait(fut, loop=loop) + try: + fut.result() + except exceptions.CancelledError as exc: + raise exceptions.TimeoutError() from exc + else: + raise exceptions.TimeoutError() waiter = loop.create_future() timeout_handle = loop.call_later(timeout, _release_waiter, waiter) diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index f9db066ce89837..511961c32005a0 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -1131,6 +1131,9 @@ async def inner(): nonlocal task_done try: await asyncio.sleep(0.2) + except asyncio.CancelledError: + await asyncio.sleep(_EPSILON) + raise finally: task_done = True @@ -1145,6 +1148,34 @@ async def inner(): chained = cm.exception.__context__ self.assertEqual(type(chained), asyncio.CancelledError) + def test_wait_for_waits_for_task_cancellation_w_timeout_0(self): + loop = asyncio.new_event_loop() + self.addCleanup(loop.close) + + task_done = False + + async def foo(): + async def inner(): + nonlocal task_done + try: + await asyncio.sleep(10) + except asyncio.CancelledError: + await asyncio.sleep(_EPSILON) + raise + finally: + task_done = True + + inner_task = self.new_task(loop, inner()) + await asyncio.sleep(_EPSILON) + await asyncio.wait_for(inner_task, timeout=0) + + with self.assertRaises(asyncio.TimeoutError) as cm: + loop.run_until_complete(foo()) + + self.assertTrue(task_done) + chained = cm.exception.__context__ + self.assertEqual(type(chained), asyncio.CancelledError) + def test_wait_for_reraises_exception_during_cancellation(self): loop = asyncio.new_event_loop() self.addCleanup(loop.close) diff --git a/Misc/NEWS.d/next/Library/2020-08-15-15-50-12.bpo-32751.85je5X.rst b/Misc/NEWS.d/next/Library/2020-08-15-15-50-12.bpo-32751.85je5X.rst new file mode 100644 index 00000000000000..c172ce5d9e9487 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-08-15-15-50-12.bpo-32751.85je5X.rst @@ -0,0 +1,3 @@ +When cancelling the task due to a timeout, :meth:`asyncio.wait_for` will now +wait until the cancellation is complete also in the case when *timeout* is +<= 0, like it does with positive timeouts. From a2118a14627256197bddcf4fcecad4c264c1e39d Mon Sep 17 00:00:00 2001 From: Elvis Pranskevichus Date: Wed, 26 Aug 2020 09:42:45 -0700 Subject: [PATCH 08/63] bpo-37658: Fix asyncio.wait_for() to respect waited task status (#21894) Currently, if `asyncio.wait_for()` itself is cancelled it will always raise `CancelledError` regardless if the underlying task is still running. This is similar to a race with the timeout, which is handled already. --- Lib/asyncio/tasks.py | 9 ++++++--- Lib/test/test_asyncio/test_tasks.py | 16 ++++++++++++++++ .../2020-08-15-15-21-40.bpo-37658.f9nivB.rst | 2 ++ 3 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2020-08-15-15-21-40.bpo-37658.f9nivB.rst diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 7ecec9638489df..8b05434f273b52 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -465,9 +465,12 @@ async def wait_for(fut, timeout, *, loop=None): try: await waiter except exceptions.CancelledError: - fut.remove_done_callback(cb) - fut.cancel() - raise + if fut.done(): + return fut.result() + else: + fut.remove_done_callback(cb) + fut.cancel() + raise if fut.done(): return fut.result() diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 511961c32005a0..74fc1e4a42133c 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -1120,6 +1120,22 @@ def gen(): res = loop.run_until_complete(task) self.assertEqual(res, "ok") + def test_wait_for_cancellation_race_condition(self): + def gen(): + yield 0.1 + yield 0.1 + yield 0.1 + yield 0.1 + + loop = self.new_test_loop(gen) + + fut = self.new_future(loop) + loop.call_later(0.1, fut.set_result, "ok") + task = loop.create_task(asyncio.wait_for(fut, timeout=1)) + loop.call_later(0.1, task.cancel) + res = loop.run_until_complete(task) + self.assertEqual(res, "ok") + def test_wait_for_waits_for_task_cancellation(self): loop = asyncio.new_event_loop() self.addCleanup(loop.close) diff --git a/Misc/NEWS.d/next/Library/2020-08-15-15-21-40.bpo-37658.f9nivB.rst b/Misc/NEWS.d/next/Library/2020-08-15-15-21-40.bpo-37658.f9nivB.rst new file mode 100644 index 00000000000000..694fbbbf346dc8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-08-15-15-21-40.bpo-37658.f9nivB.rst @@ -0,0 +1,2 @@ +:meth:`asyncio.wait_for` now properly handles races between cancellation of +itself and the completion of the wrapped awaitable. From 31967fd8d0220af84e2698172d1378bffc8cd851 Mon Sep 17 00:00:00 2001 From: Dong-hee Na Date: Wed, 26 Aug 2020 17:22:27 +0000 Subject: [PATCH 09/63] bpo-40077: Convert _operator to use PyType_FromSpec (GH-21954) --- .../2020-08-25-22-43-33.bpo-40077.vcxSUa.rst | 1 + Modules/_operator.c | 298 +++++++++--------- 2 files changed, 143 insertions(+), 156 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2020-08-25-22-43-33.bpo-40077.vcxSUa.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-08-25-22-43-33.bpo-40077.vcxSUa.rst b/Misc/NEWS.d/next/Core and Builtins/2020-08-25-22-43-33.bpo-40077.vcxSUa.rst new file mode 100644 index 00000000000000..ee950010e6d13f --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-08-25-22-43-33.bpo-40077.vcxSUa.rst @@ -0,0 +1 @@ +Convert :mod:`_operator` to use :c:func:`PyType_FromSpec`. diff --git a/Modules/_operator.c b/Modules/_operator.c index 8a54829e5bbcc8..c9d38aa3423667 100644 --- a/Modules/_operator.c +++ b/Modules/_operator.c @@ -3,6 +3,20 @@ #include "clinic/_operator.c.h" +typedef struct { + PyObject *itemgetter_type; + PyObject *attrgetter_type; + PyObject *methodcaller_type; +} _operator_state; + +static inline _operator_state* +get_operator_state(PyObject *module) +{ + void *state = PyModule_GetState(module); + assert(state != NULL); + return (_operator_state *)state; +} + /*[clinic input] module _operator [clinic start generated code]*/ @@ -942,8 +956,6 @@ typedef struct { Py_ssize_t index; // -1 unless *item* is a single non-negative integer index } itemgetterobject; -static PyTypeObject itemgetter_type; - /* AC 3.5: treats first argument as an iterable, otherwise uses *args */ static PyObject * itemgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) @@ -960,13 +972,15 @@ itemgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if (nitems <= 1) { if (!PyArg_UnpackTuple(args, "itemgetter", 1, 1, &item)) return NULL; - } else + } else { item = args; - + } + _operator_state *state = PyType_GetModuleState(type); /* create itemgetterobject structure */ - ig = PyObject_GC_New(itemgetterobject, &itemgetter_type); - if (ig == NULL) + ig = PyObject_GC_New(itemgetterobject, (PyTypeObject *) state->itemgetter_type); + if (ig == NULL) { return NULL; + } Py_INCREF(item); ig->item = item; @@ -994,9 +1008,11 @@ itemgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static void itemgetter_dealloc(itemgetterobject *ig) { + PyTypeObject *tp = Py_TYPE(ig); PyObject_GC_UnTrack(ig); Py_XDECREF(ig->item); - PyObject_GC_Del(ig); + tp->tp_free(ig); + Py_DECREF(tp); } static int @@ -1093,49 +1109,25 @@ Return a callable object that fetches the given item(s) from its operand.\n\ After f = itemgetter(2), the call f(r) returns r[2].\n\ After g = itemgetter(2, 5, 3), the call g(r) returns (r[2], r[5], r[3])"); -static PyTypeObject itemgetter_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "operator.itemgetter", /* tp_name */ - sizeof(itemgetterobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)itemgetter_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - (reprfunc)itemgetter_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - (ternaryfunc)itemgetter_call, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ - itemgetter_doc, /* tp_doc */ - (traverseproc)itemgetter_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - itemgetter_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - itemgetter_new, /* tp_new */ - 0, /* tp_free */ +static PyType_Slot itemgetter_type_slots[] = { + {Py_tp_doc, (void *)itemgetter_doc}, + {Py_tp_dealloc, itemgetter_dealloc}, + {Py_tp_call, itemgetter_call}, + {Py_tp_traverse, itemgetter_traverse}, + {Py_tp_methods, itemgetter_methods}, + {Py_tp_new, itemgetter_new}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_repr, itemgetter_repr}, + {0, 0} }; +static PyType_Spec itemgetter_type_spec = { + .name = "operator.itemgetter", + .basicsize = sizeof(itemgetterobject), + .itemsize = 0, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + .slots = itemgetter_type_slots, +}; /* attrgetter object **********************************************************/ @@ -1145,8 +1137,6 @@ typedef struct { PyObject *attr; } attrgetterobject; -static PyTypeObject attrgetter_type; - /* AC 3.5: treats first argument as an iterable, otherwise uses *args */ static PyObject * attrgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) @@ -1246,8 +1236,9 @@ attrgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) } } + _operator_state *state = PyType_GetModuleState(type); /* create attrgetterobject structure */ - ag = PyObject_GC_New(attrgetterobject, &attrgetter_type); + ag = PyObject_GC_New(attrgetterobject, (PyTypeObject *)state->attrgetter_type); if (ag == NULL) { Py_DECREF(attr); return NULL; @@ -1263,9 +1254,11 @@ attrgetter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static void attrgetter_dealloc(attrgetterobject *ag) { + PyTypeObject *tp = Py_TYPE(ag); PyObject_GC_UnTrack(ag); Py_XDECREF(ag->attr); - PyObject_GC_Del(ag); + tp->tp_free(ag); + Py_DECREF(tp); } static int @@ -1438,47 +1431,24 @@ After g = attrgetter('name', 'date'), the call g(r) returns (r.name, r.date).\n\ After h = attrgetter('name.first', 'name.last'), the call h(r) returns\n\ (r.name.first, r.name.last)."); -static PyTypeObject attrgetter_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "operator.attrgetter", /* tp_name */ - sizeof(attrgetterobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)attrgetter_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - (reprfunc)attrgetter_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - (ternaryfunc)attrgetter_call, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ - attrgetter_doc, /* tp_doc */ - (traverseproc)attrgetter_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - attrgetter_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - attrgetter_new, /* tp_new */ - 0, /* tp_free */ +static PyType_Slot attrgetter_type_slots[] = { + {Py_tp_doc, (void *)attrgetter_doc}, + {Py_tp_dealloc, attrgetter_dealloc}, + {Py_tp_call, attrgetter_call}, + {Py_tp_traverse, attrgetter_traverse}, + {Py_tp_methods, attrgetter_methods}, + {Py_tp_new, attrgetter_new}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_repr, attrgetter_repr}, + {0, 0} +}; + +static PyType_Spec attrgetter_type_spec = { + .name = "operator.attrgetter", + .basicsize = sizeof(attrgetterobject), + .itemsize = 0, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + .slots = attrgetter_type_slots, }; @@ -1491,8 +1461,6 @@ typedef struct { PyObject *kwds; } methodcallerobject; -static PyTypeObject methodcaller_type; - /* AC 3.5: variable number of arguments, not currently support by AC */ static PyObject * methodcaller_new(PyTypeObject *type, PyObject *args, PyObject *kwds) @@ -1513,10 +1481,12 @@ methodcaller_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; } + _operator_state *state = PyType_GetModuleState(type); /* create methodcallerobject structure */ - mc = PyObject_GC_New(methodcallerobject, &methodcaller_type); - if (mc == NULL) + mc = PyObject_GC_New(methodcallerobject, (PyTypeObject *)state->methodcaller_type); + if (mc == NULL) { return NULL; + } name = PyTuple_GET_ITEM(args, 0); Py_INCREF(name); @@ -1539,11 +1509,13 @@ methodcaller_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static void methodcaller_dealloc(methodcallerobject *mc) { + PyTypeObject *tp = Py_TYPE(mc); PyObject_GC_UnTrack(mc); Py_XDECREF(mc->name); Py_XDECREF(mc->args); Py_XDECREF(mc->kwds); - PyObject_GC_Del(mc); + tp->tp_free(mc); + Py_DECREF(tp); } static int @@ -1704,63 +1676,52 @@ After f = methodcaller('name'), the call f(r) returns r.name().\n\ After g = methodcaller('name', 'date', foo=1), the call g(r) returns\n\ r.name('date', foo=1)."); -static PyTypeObject methodcaller_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "operator.methodcaller", /* tp_name */ - sizeof(methodcallerobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)methodcaller_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - (reprfunc)methodcaller_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - (ternaryfunc)methodcaller_call, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ - methodcaller_doc, /* tp_doc */ - (traverseproc)methodcaller_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - methodcaller_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - methodcaller_new, /* tp_new */ - 0, /* tp_free */ +static PyType_Slot methodcaller_type_slots[] = { + {Py_tp_doc, (void *)methodcaller_doc}, + {Py_tp_dealloc, methodcaller_dealloc}, + {Py_tp_call, methodcaller_call}, + {Py_tp_traverse, methodcaller_traverse}, + {Py_tp_methods, methodcaller_methods}, + {Py_tp_new, methodcaller_new}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_repr, methodcaller_repr}, + {0, 0} }; +static PyType_Spec methodcaller_type_spec = { + .name = "operator.methodcaller", + .basicsize = sizeof(methodcallerobject), + .itemsize = 0, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + .slots = methodcaller_type_slots, +}; static int operator_exec(PyObject *module) { - PyTypeObject *types[] = { - &itemgetter_type, - &attrgetter_type, - &methodcaller_type - }; + _operator_state *state = get_operator_state(module); + state->attrgetter_type = PyType_FromModuleAndSpec(module, &attrgetter_type_spec, NULL); + if (state->attrgetter_type == NULL) { + return -1; + } + if (PyModule_AddType(module, (PyTypeObject *)state->attrgetter_type) < 0) { + return -1; + } - for (size_t i = 0; i < Py_ARRAY_LENGTH(types); i++) { - if (PyModule_AddType(module, types[i]) < 0) { - return -1; - } + state->itemgetter_type = PyType_FromModuleAndSpec(module, &itemgetter_type_spec, NULL); + if (state->itemgetter_type == NULL) { + return -1; + } + if (PyModule_AddType(module, (PyTypeObject *)state->itemgetter_type) < 0) { + return -1; + } + + state->methodcaller_type = PyType_FromModuleAndSpec(module, &methodcaller_type_spec, NULL); + if (state->methodcaller_type == NULL) { + return -1; + } + if (PyModule_AddType(module, (PyTypeObject *)state->methodcaller_type) < 0) { + return -1; } return 0; @@ -1772,17 +1733,42 @@ static struct PyModuleDef_Slot operator_slots[] = { {0, NULL} }; +static int +operator_traverse(PyObject *module, visitproc visit, void *arg) +{ + _operator_state *state = get_operator_state(module); + Py_VISIT(state->attrgetter_type); + Py_VISIT(state->itemgetter_type); + Py_VISIT(state->methodcaller_type); + return 0; +} + +static int +operator_clear(PyObject *module) +{ + _operator_state *state = get_operator_state(module); + Py_CLEAR(state->attrgetter_type); + Py_CLEAR(state->itemgetter_type); + Py_CLEAR(state->methodcaller_type); + return 0; +} + +static void +operator_free(void *module) +{ + operator_clear((PyObject *)module); +} static struct PyModuleDef operatormodule = { PyModuleDef_HEAD_INIT, - "_operator", - operator_doc, - 0, - operator_methods, - operator_slots, - NULL, - NULL, - NULL + .m_name = "_operator", + .m_doc = operator_doc, + .m_size = sizeof(_operator_state), + .m_methods = operator_methods, + .m_slots = operator_slots, + .m_traverse = operator_traverse, + .m_clear = operator_clear, + .m_free = operator_free, }; PyMODINIT_FUNC From 82e79480d6e61940d7007d9026fbff0b1a11ad9a Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Wed, 26 Aug 2020 13:09:40 -0700 Subject: [PATCH 10/63] Fix typos in comment (GH-21966) --- Modules/mathmodule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 1d6174132814b2..1704d8efd31c3a 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -2440,7 +2440,7 @@ addend should be in the range: 0.5 <= |x| <= 1.0. Accordingly, scaling or division by *max* should not be skipped even if not otherwise needed to prevent overflow or loss of precision. -The assertion that hi*hi >= 1.0 is a bit subtle. Each vector element +The assertion that hi*hi <= 1.0 is a bit subtle. Each vector element gets scaled to a magnitude below 1.0. The Veltkamp-Dekker splitting algorithm gives a *hi* value that is correctly rounded to half precision. When a value at or below 1.0 is correctly rounded, it @@ -2458,7 +2458,7 @@ The correction is the first order term of the Maclaurin series expansion of sqrt(h**2 + x) == h + x/(2*h) + O(x**2). Essentially, this differential correction is equivalent to one -refinement step in the Newton divide-and-average square root +refinement step in Newton's divide-and-average square root algorithm, effectively doubling the number of accurate bits. This technique is used in Dekker's SQRT2 algorithm and again in Borges' ALGORITHM 4 and 5. From 94ad6c674f7687ef22853cb8d42b440d6b42ddc8 Mon Sep 17 00:00:00 2001 From: Dong-hee Na Date: Tue, 12 Jun 2018 23:30:45 +0900 Subject: [PATCH 11/63] bpo-33660: Fix PosixPath to resolve a relative path on root --- Lib/pathlib.py | 5 ++++- Lib/test/test_pathlib.py | 9 +++++++++ .../Library/2018-06-12-23-30-41.bpo-33660.AdDn5Z.rst | 2 ++ 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2018-06-12-23-30-41.bpo-33660.AdDn5Z.rst diff --git a/Lib/pathlib.py b/Lib/pathlib.py index 9f5e27b91178e6..babc443dd3b304 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -329,7 +329,10 @@ def _resolve(path, rest): # parent dir path, _, _ = path.rpartition(sep) continue - newpath = path + sep + name + if path.endswith(sep): + newpath = path + name + else: + newpath = path + sep + name if newpath in seen: # Already seen this path path = seen[newpath] diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 04f7c3d86671bf..2cb6738a295b64 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -2349,6 +2349,15 @@ def test_open_mode(self): st = os.stat(join('other_new_file')) self.assertEqual(stat.S_IMODE(st.st_mode), 0o644) + def test_resolve_root(self): + current_directory = os.getcwd() + try: + os.chdir('/') + p = self.cls('spam') + self.assertEqual(str(p.resolve()), '/spam') + finally: + os.chdir(current_directory) + def test_touch_mode(self): old_mask = os.umask(0) self.addCleanup(os.umask, old_mask) diff --git a/Misc/NEWS.d/next/Library/2018-06-12-23-30-41.bpo-33660.AdDn5Z.rst b/Misc/NEWS.d/next/Library/2018-06-12-23-30-41.bpo-33660.AdDn5Z.rst new file mode 100644 index 00000000000000..cce3dbb1c6ea5b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-06-12-23-30-41.bpo-33660.AdDn5Z.rst @@ -0,0 +1,2 @@ +Fix pathlib.PosixPath to resolve a relative path located on the root +directory properly. From 8c58d2a216ca2b5965361df9b8d8944bc7d4854d Mon Sep 17 00:00:00 2001 From: MingZhe Hu Date: Thu, 27 Aug 2020 08:42:37 +0800 Subject: [PATCH 12/63] bpo-41624: fix documentation of typing.Coroutine (GH-21952) --- Doc/library/typing.rst | 2 +- .../next/Documentation/2020-08-25-15-11-23.bpo-41624.ddjJlN.rst | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Documentation/2020-08-25-15-11-23.bpo-41624.ddjJlN.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 8208680669de6e..9f98f8ce3f642d 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -1365,7 +1365,7 @@ Corresponding to other types in :mod:`collections.abc` Asynchronous programming """""""""""""""""""""""" -.. class:: Coroutine(Awaitable[V_co], Generic[T_co T_contra, V_co]) +.. class:: Coroutine(Awaitable[V_co], Generic[T_co, T_contra, V_co]) A generic version of :class:`collections.abc.Coroutine`. The variance and order of type variables diff --git a/Misc/NEWS.d/next/Documentation/2020-08-25-15-11-23.bpo-41624.ddjJlN.rst b/Misc/NEWS.d/next/Documentation/2020-08-25-15-11-23.bpo-41624.ddjJlN.rst new file mode 100644 index 00000000000000..bdbc5a445f3390 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2020-08-25-15-11-23.bpo-41624.ddjJlN.rst @@ -0,0 +1 @@ +Fix the signature of :class:`typing.Coroutine`. From b260635b3db5715adf7a9a3df542c171fb7296ef Mon Sep 17 00:00:00 2001 From: Mason <38963371+nosamproductions@users.noreply.github.com> Date: Wed, 26 Aug 2020 19:49:14 -0500 Subject: [PATCH 13/63] Add missing word (GH-21936) "data to lost" -> "data to be lost" --- Doc/library/multiprocessing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst index 28510acd52bd46..f8e7556f25b4e0 100644 --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -861,7 +861,7 @@ For an example of the usage of queues for interprocess communication see A better name for this method might be ``allow_exit_without_flush()``. It is likely to cause enqueued - data to lost, and you almost certainly will not need to use it. + data to be lost, and you almost certainly will not need to use it. It is really only there if you need the current process to exit immediately without waiting to flush enqueued data to the underlying pipe, and you don't care about lost data. From 022bc7572f061e1d1132a4db9d085b29707701e7 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 27 Aug 2020 01:51:12 +0100 Subject: [PATCH 14/63] bpo-41609: Fix output of pdb's whatis command for instance methods (GH-21935) --- Lib/pdb.py | 12 +++--- Lib/test/test_pdb.py | 41 +++++++++++++++++++ .../2020-08-21-15-51-15.bpo-41609.JmiUKG.rst | 1 + 3 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2020-08-21-15-51-15.bpo-41609.JmiUKG.rst diff --git a/Lib/pdb.py b/Lib/pdb.py index 081023526c0ea0..d7d957159458be 100755 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -1312,21 +1312,21 @@ def do_whatis(self, arg): # _getval() already printed the error return code = None - # Is it a function? + # Is it an instance method? try: - code = value.__code__ + code = value.__func__.__code__ except Exception: pass if code: - self.message('Function %s' % code.co_name) + self.message('Method %s' % code.co_name) return - # Is it an instance method? + # Is it a function? try: - code = value.__func__.__code__ + code = value.__code__ except Exception: pass if code: - self.message('Method %s' % code.co_name) + self.message('Function %s' % code.co_name) return # Is it a class? if value.__class__ is type: diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 1a2bbb382e8642..e56451360d6438 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -425,6 +425,47 @@ def test_list_commands(): (Pdb) continue """ +def test_pdb_whatis_command(): + """Test the whatis command + + >>> myvar = (1,2) + >>> def myfunc(): + ... pass + + >>> class MyClass: + ... def mymethod(self): + ... pass + + >>> def test_function(): + ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + + >>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE + ... 'whatis myvar', + ... 'whatis myfunc', + ... 'whatis MyClass', + ... 'whatis MyClass()', + ... 'whatis MyClass.mymethod', + ... 'whatis MyClass().mymethod', + ... 'continue', + ... ]): + ... test_function() + --Return-- + > (2)test_function()->None + -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + (Pdb) whatis myvar + + (Pdb) whatis myfunc + Function myfunc + (Pdb) whatis MyClass + Class test.test_pdb.MyClass + (Pdb) whatis MyClass() + + (Pdb) whatis MyClass.mymethod + Function mymethod + (Pdb) whatis MyClass().mymethod + Method mymethod + (Pdb) continue + """ def test_post_mortem(): """Test post mortem traceback debugging. diff --git a/Misc/NEWS.d/next/Library/2020-08-21-15-51-15.bpo-41609.JmiUKG.rst b/Misc/NEWS.d/next/Library/2020-08-21-15-51-15.bpo-41609.JmiUKG.rst new file mode 100644 index 00000000000000..ecaf40eee7babf --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-08-21-15-51-15.bpo-41609.JmiUKG.rst @@ -0,0 +1 @@ +The pdb whatis command correctly reports instance methods as 'Method' rather than 'Function'. \ No newline at end of file From 97eaf2b5e5c826b9abe59896a363853bef55c5d9 Mon Sep 17 00:00:00 2001 From: wmeehan Date: Thu, 27 Aug 2020 01:45:25 -0400 Subject: [PATCH 15/63] bpo-41524: fix pointer bug in PyOS_mystr{n}icmp (GH-21845) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * bpo-41524: fix pointer bug in PyOS_mystr{n}icmp The existing implementations of PyOS_mystrnicmp and PyOS_mystricmp can increment pointers beyond the end of a string. This commit fixes those cases by moving the mutation out of the condition. * 📜🤖 Added by blurb_it. * Address comments Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> --- .../2020-08-12-17-09-06.bpo-41524.u6Xfr2.rst | 2 ++ Python/pystrcmp.c | 18 +++++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2020-08-12-17-09-06.bpo-41524.u6Xfr2.rst diff --git a/Misc/NEWS.d/next/C API/2020-08-12-17-09-06.bpo-41524.u6Xfr2.rst b/Misc/NEWS.d/next/C API/2020-08-12-17-09-06.bpo-41524.u6Xfr2.rst new file mode 100644 index 00000000000000..4704e29be29bb0 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2020-08-12-17-09-06.bpo-41524.u6Xfr2.rst @@ -0,0 +1,2 @@ +Fix bug in PyOS_mystrnicmp and PyOS_mystricmp that incremented +pointers beyond the end of a string. \ No newline at end of file diff --git a/Python/pystrcmp.c b/Python/pystrcmp.c index f9c2277cb56dc7..9224ce4c706055 100644 --- a/Python/pystrcmp.c +++ b/Python/pystrcmp.c @@ -6,21 +6,25 @@ int PyOS_mystrnicmp(const char *s1, const char *s2, Py_ssize_t size) { + const unsigned char *p1, *p2; if (size == 0) return 0; - while ((--size > 0) && - (tolower((unsigned)*s1) == tolower((unsigned)*s2))) { - if (!*s1++ || !*s2++) - break; + p1 = (const unsigned char *)s1; + p2 = (const unsigned char *)s2; + for (; (--size > 0) && *p1 && *p2 && (tolower(*p1) == tolower(*p2)); + p1++, p2++) { + ; } - return tolower((unsigned)*s1) - tolower((unsigned)*s2); + return tolower(*p1) - tolower(*p2); } int PyOS_mystricmp(const char *s1, const char *s2) { - while (*s1 && (tolower((unsigned)*s1++) == tolower((unsigned)*s2++))) { + const unsigned char *p1 = (const unsigned char *)s1; + const unsigned char *p2 = (const unsigned char *)s2; + for (; *p1 && *p2 && (tolower(*p1) == tolower(*p2)); p1++, p2++) { ; } - return (tolower((unsigned)*s1) - tolower((unsigned)*s2)); + return (tolower(*p1) - tolower(*p2)); } From 398575c210f79627830c5c470184f54ace950ac6 Mon Sep 17 00:00:00 2001 From: Zackery Spytz Date: Thu, 27 Aug 2020 05:28:16 -0600 Subject: [PATCH 16/63] bpo-41634: Fix a typo in the curses documentation (GH-21958) --- Doc/library/curses.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/curses.rst b/Doc/library/curses.rst index 0b687db1bd2c4d..3684d54d4ecade 100644 --- a/Doc/library/curses.rst +++ b/Doc/library/curses.rst @@ -717,7 +717,7 @@ the following methods and attributes: window.addch(y, x, ch[, attr]) Paint character *ch* at ``(y, x)`` with attributes *attr*, overwriting any - character previously painter at that location. By default, the character + character previously painted at that location. By default, the character position and attributes are the current settings for the window object. .. note:: From d9a966ae08258da2ce2a432c943d8194760f09c4 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Thu, 27 Aug 2020 15:36:48 +0200 Subject: [PATCH 17/63] bpo-38787: Clarify docs for PyType_GetModule and warn against common mistake (GH-20215) --- Doc/c-api/type.rst | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Doc/c-api/type.rst b/Doc/c-api/type.rst index f387279d143eec..7309d7ee2cd398 100644 --- a/Doc/c-api/type.rst +++ b/Doc/c-api/type.rst @@ -117,6 +117,13 @@ Type Objects If no module is associated with the given type, sets :py:class:`TypeError` and returns ``NULL``. + This function is usually used to get the module in which a method is defined. + Note that in such a method, ``PyType_GetModule(Py_TYPE(self))`` + may not return the intended result. + ``Py_TYPE(self)`` may be a *subclass* of the intended class, and subclasses + are not necessarily defined in the same module as their superclass. + See :c:type:`PyCMethod` to get the class that defines the method. + .. versionadded:: 3.9 .. c:function:: void* PyType_GetModuleState(PyTypeObject *type) @@ -151,9 +158,12 @@ The following functions and structs are used to create If *bases* is ``NULL``, the *Py_tp_base* slot is used instead. If that also is ``NULL``, the new type derives from :class:`object`. - The *module* must be a module object or ``NULL``. + The *module* argument can be used to record the module in which the new + class is defined. It must be a module object or ``NULL``. If not ``NULL``, the module is associated with the new type and can later be retreived with :c:func:`PyType_GetModule`. + The associated module is not inherited by subclasses; it must be specified + for each class individually. This function calls :c:func:`PyType_Ready` on the new type. From 8784d3300ec4ffc58bc0e9ab3cff9a24187dbe4c Mon Sep 17 00:00:00 2001 From: SarahPythonista <4283226+SarahPythonista@users.noreply.github.com> Date: Fri, 28 Aug 2020 11:47:58 -0700 Subject: [PATCH 18/63] Fix error in argparse documentation example (GH-17399) Automerge-Triggered-By: @rhettinger --- Doc/library/argparse.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index 0b64dfe47f7689..7a7a4cf94979a1 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -1162,8 +1162,8 @@ keyword argument to :meth:`~ArgumentParser.add_argument`:: >>> parser.parse_args(['--foo', 'BAR']) Namespace(foo='BAR') >>> parser.parse_args([]) - usage: argparse.py [-h] [--foo FOO] - argparse.py: error: option --foo is required + usage: [-h] --foo FOO + : error: the following arguments are required: --foo As the example shows, if an option is marked as ``required``, :meth:`~ArgumentParser.parse_args` will report an error if that option is not From e6dcd371b2c54a94584dd124e8c592a496d46a47 Mon Sep 17 00:00:00 2001 From: Stefan Krah Date: Sat, 29 Aug 2020 17:00:08 +0200 Subject: [PATCH 19/63] bpo-19521: Fix parallel build race condition on AIX (GH-21997) Patch by Michael Haubenwallner. --- Makefile.pre.in | 12 ++++++++++-- configure | 31 ++++++++++++++++++++++--------- configure.ac | 27 ++++++++++++++++++--------- 3 files changed, 50 insertions(+), 20 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in index 0a19313ea99397..5d3ac705a36253 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -161,6 +161,10 @@ BLDSHARED= @BLDSHARED@ $(PY_CORE_LDFLAGS) LDCXXSHARED= @LDCXXSHARED@ DESTSHARED= $(BINLIBDEST)/lib-dynload +# List of exported symbols for AIX +EXPORTSYMS= @EXPORTSYMS@ +EXPORTSFROM= @EXPORTSFROM@ + # Executable suffix (.exe on Windows and Mac OS X) EXE= @EXEEXT@ BUILDEXE= @BUILDEXEEXT@ @@ -571,7 +575,7 @@ clinic: check-clean-src $(srcdir)/Modules/_blake2/blake2s_impl.c $(PYTHON_FOR_REGEN) $(srcdir)/Tools/clinic/clinic.py --make --srcdir $(srcdir) # Build the interpreter -$(BUILDPYTHON): Programs/python.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY) +$(BUILDPYTHON): Programs/python.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY) $(EXPORTSYMS) $(LINKCC) $(PY_CORE_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/python.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) platform: $(BUILDPYTHON) pybuilddir.txt @@ -643,6 +647,10 @@ libpython$(LDVERSION).dylib: $(LIBRARY_OBJS) libpython$(VERSION).sl: $(LIBRARY_OBJS) $(LDSHARED) -o $@ $(LIBRARY_OBJS) $(MODLIBS) $(SHLIBS) $(LIBC) $(LIBM) +# List of exported symbols for AIX +Modules/python.exp: $(LIBRARY) + $(srcdir)/Modules/makexp_aix $@ "$(EXPORTSFROM)" $? + # Copy up the gdb python hooks into a position where they can be automatically # loaded by gdb during Lib/test/test_gdb.py # @@ -702,7 +710,7 @@ Makefile Modules/config.c: Makefile.pre \ @echo "The Makefile was updated, you may need to re-run make." -Programs/_testembed: Programs/_testembed.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY) +Programs/_testembed: Programs/_testembed.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY) $(EXPORTSYMS) $(LINKCC) $(PY_CORE_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/_testembed.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) ############################################################################ diff --git a/configure b/configure index 69e975a4e8ef3c..4c18ae7e364ca1 100755 --- a/configure +++ b/configure @@ -700,6 +700,8 @@ ARFLAGS ac_ct_AR AR GNULD +EXPORTSFROM +EXPORTSYMS LINKCC LDVERSION RUNSHARED @@ -5799,8 +5801,6 @@ LDVERSION="$VERSION" # If CXX is set, and if it is needed to link a main function that was # compiled with CXX, LINKCC is CXX instead. Always using CXX is undesirable: # python might then depend on the C++ runtime -# This is altered for AIX in order to build the export list before -# linking. { $as_echo "$as_me:${as_lineno-$LINENO}: checking LINKCC" >&5 $as_echo_n "checking LINKCC... " >&6; } @@ -5808,13 +5808,6 @@ if test -z "$LINKCC" then LINKCC='$(PURIFY) $(MAINCC)' case $ac_sys_system in - AIX*) - exp_extra="\"\"" - if test $ac_sys_release -ge 5 -o \ - $ac_sys_release -eq 4 -a `uname -r` -ge 2 ; then - exp_extra="." - fi - LINKCC="\$(srcdir)/Modules/makexp_aix Modules/python.exp $exp_extra \$(LIBRARY); $LINKCC";; QNX*) # qcc must be used because the other compilers do not # support -N. @@ -5824,6 +5817,26 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LINKCC" >&5 $as_echo "$LINKCC" >&6; } +# EXPORTSYMS holds the list of exported symbols for AIX. +# EXPORTSFROM holds the module name exporting symbols on AIX. +EXPORTSYMS= +EXPORTSFROM= + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking EXPORTSYMS" >&5 +$as_echo_n "checking EXPORTSYMS... " >&6; } +case $ac_sys_system in +AIX*) + EXPORTSYMS="Modules/python.exp" + if test $ac_sys_release -ge 5 -o \ + $ac_sys_release -eq 4 -a `uname -r` -ge 2 ; then + EXPORTSFROM=. # the main executable + fi + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $EXPORTSYMS" >&5 +$as_echo "$EXPORTSYMS" >&6; } + # GNULD is set to "yes" if the GNU linker is used. If this goes wrong # make sure we default having it set to "no": this is used by # distutils.unixccompiler to know if it should add --enable-new-dtags diff --git a/configure.ac b/configure.ac index 07c0585432b065..3b40f39124dad5 100644 --- a/configure.ac +++ b/configure.ac @@ -1024,21 +1024,12 @@ LDVERSION="$VERSION" # If CXX is set, and if it is needed to link a main function that was # compiled with CXX, LINKCC is CXX instead. Always using CXX is undesirable: # python might then depend on the C++ runtime -# This is altered for AIX in order to build the export list before -# linking. AC_SUBST(LINKCC) AC_MSG_CHECKING(LINKCC) if test -z "$LINKCC" then LINKCC='$(PURIFY) $(MAINCC)' case $ac_sys_system in - AIX*) - exp_extra="\"\"" - if test $ac_sys_release -ge 5 -o \ - $ac_sys_release -eq 4 -a `uname -r` -ge 2 ; then - exp_extra="." - fi - LINKCC="\$(srcdir)/Modules/makexp_aix Modules/python.exp $exp_extra \$(LIBRARY); $LINKCC";; QNX*) # qcc must be used because the other compilers do not # support -N. @@ -1047,6 +1038,24 @@ then fi AC_MSG_RESULT($LINKCC) +# EXPORTSYMS holds the list of exported symbols for AIX. +# EXPORTSFROM holds the module name exporting symbols on AIX. +EXPORTSYMS= +EXPORTSFROM= +AC_SUBST(EXPORTSYMS) +AC_SUBST(EXPORTSFROM) +AC_MSG_CHECKING(EXPORTSYMS) +case $ac_sys_system in +AIX*) + EXPORTSYMS="Modules/python.exp" + if test $ac_sys_release -ge 5 -o \ + $ac_sys_release -eq 4 -a `uname -r` -ge 2 ; then + EXPORTSFROM=. # the main executable + fi + ;; +esac +AC_MSG_RESULT($EXPORTSYMS) + # GNULD is set to "yes" if the GNU linker is used. If this goes wrong # make sure we default having it set to "no": this is used by # distutils.unixccompiler to know if it should add --enable-new-dtags From 27de28607a248e5ffb8838162fca466a58c2e284 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Sat, 29 Aug 2020 09:11:04 -0700 Subject: [PATCH 20/63] bpo-41513: Save unnecessary steps in the hypot() calculation (#21994) --- Modules/mathmodule.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 1704d8efd31c3a..4ff2a069a76c7b 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -2447,6 +2447,14 @@ precision. When a value at or below 1.0 is correctly rounded, it never goes above 1.0. And when values at or below 1.0 are squared, they remain at or below 1.0, thus preserving the summation invariant. +Another interesting assertion is that csum+lo*lo == csum. In the loop, +each scaled vector element has a magnitude less than 1.0. After the +Veltkamp split, *lo* has a maximum value of 2**-27. So the maximum +value of *lo* squared is 2**-54. The value of ulp(1.0)/2.0 is 2**-53. +Given that csum >= 1.0, we have: + lo**2 <= 2**-54 < 2**-53 == 1/2*ulp(1.0) <= ulp(csum)/2 +Since lo**2 is less than 1/2 ulp(csum), we have csum+lo*lo == csum. + The square root differential correction is needed because a correctly rounded square root of a correctly rounded sum of squares can still be off by as much as one ulp. @@ -2519,11 +2527,8 @@ vector_norm(Py_ssize_t n, double *vec, double max, int found_nan) csum += x; frac += (oldcsum - csum) + x; - x = lo * lo; - assert(fabs(csum) >= fabs(x)); - oldcsum = csum; - csum += x; - frac += (oldcsum - csum) + x; + assert(csum + lo * lo == csum); + frac += lo * lo; } h = sqrt(csum - 1.0 + frac); From c68c5af2dc5ada8875a662f2beaac6234eae2a5a Mon Sep 17 00:00:00 2001 From: Roger Iyengar Date: Sat, 29 Aug 2020 19:47:38 -0400 Subject: [PATCH 21/63] Improve asyncio-dev 'Concurrency and Multithreading' docs (GH-20882) I added some information to the `Concurrency and Multithreading` section of the `Developing with asyncio` guide. This is all information that would have helped me when I started using asyncio. I incorrectly assumed that `loop.call_soon_threadsafe()` and `run_coroutine_threadsafe()` could be called from a thread in a process separate from the one that the event loop is running in. Explicitly stating that this will not work will probably help some people starting out with asyncio in the future. I also added references to some other functions that can be used for inter-process communication without blocking the event loop. The section already mentions running blocking code in a ThreadPoolExecutor, but I think listing these other options in this section will also be helpful. --- Doc/library/asyncio-dev.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Doc/library/asyncio-dev.rst b/Doc/library/asyncio-dev.rst index 77f80671978369..02a00033152aba 100644 --- a/Doc/library/asyncio-dev.rst +++ b/Doc/library/asyncio-dev.rst @@ -107,6 +107,16 @@ The :meth:`loop.run_in_executor` method can be used with a blocking code in a different OS thread without blocking the OS thread that the event loop runs in. +There is currently no way to schedule coroutines or callbacks directly +from a different process (such as one started with +:mod:`multiprocessing`). The :ref:`Event Loop Methods ` +section lists APIs that can read from pipes and watch file descriptors +without blocking the event loop. In addition, asyncio's +:ref:`Subprocess ` APIs provide a way to start a +process and communicate with it from the event loop. Lastly, the +aforementioned :meth:`loop.run_in_executor` method can also be used +with a :class:`concurrent.futures.ProcessPoolExecutor` to execute +code in a different process. .. _asyncio-handle-blocking: From 75c80b0bda89debf312f075716b8c467d411f90e Mon Sep 17 00:00:00 2001 From: Tony Solomonik Date: Sun, 30 Aug 2020 07:53:08 +0300 Subject: [PATCH 22/63] closes bpo-41533: Fix a potential memory leak when allocating a stack (GH-21847) Free the stack allocated in va_build_stack if do_mkstack fails and the stack is not a small_stack --- .../Core and Builtins/2020-08-12-20-29-57.bpo-41533.4pcVAc.rst | 2 ++ Python/modsupport.c | 3 +++ 2 files changed, 5 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2020-08-12-20-29-57.bpo-41533.4pcVAc.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-08-12-20-29-57.bpo-41533.4pcVAc.rst b/Misc/NEWS.d/next/Core and Builtins/2020-08-12-20-29-57.bpo-41533.4pcVAc.rst new file mode 100644 index 00000000000000..e166f0c0b621a4 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-08-12-20-29-57.bpo-41533.4pcVAc.rst @@ -0,0 +1,2 @@ +Free the stack allocated in ``va_build_stack`` if ``do_mkstack`` fails and +the stack is not a ``small_stack``. diff --git a/Python/modsupport.c b/Python/modsupport.c index 2637039d4a1518..2dabcf383409e9 100644 --- a/Python/modsupport.c +++ b/Python/modsupport.c @@ -622,6 +622,9 @@ va_build_stack(PyObject **small_stack, Py_ssize_t small_stack_len, va_end(lva); if (res < 0) { + if (stack != small_stack) { + PyMem_Free(stack); + } return NULL; } From 92c38164a42572e2bc0b1b1490bec2369480ae08 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Sun, 30 Aug 2020 10:00:11 -0700 Subject: [PATCH 23/63] Further improve accuracy of math.hypot() (GH-22013) --- Modules/mathmodule.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 4ff2a069a76c7b..6621951ee97d2b 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -2455,6 +2455,9 @@ Given that csum >= 1.0, we have: lo**2 <= 2**-54 < 2**-53 == 1/2*ulp(1.0) <= ulp(csum)/2 Since lo**2 is less than 1/2 ulp(csum), we have csum+lo*lo == csum. +To minimize loss of information during the accumulation of fractional +values, the lo**2 term has a separate accumulator. + The square root differential correction is needed because a correctly rounded square root of a correctly rounded sum of squares can still be off by as much as one ulp. @@ -2475,7 +2478,8 @@ Borges' ALGORITHM 4 and 5. 1. Veltkamp-Dekker splitting: http://csclub.uwaterloo.ca/~pbarfuss/dekker1971.pdf 2. Compensated summation: http://www.ti3.tu-harburg.de/paper/rump/Ru08b.pdf -3. Square root diffential correction: https://arxiv.org/pdf/1904.09481.pdf +3. Square root differential correction: https://arxiv.org/pdf/1904.09481.pdf +4. https://www.wolframalpha.com/input/?i=Maclaurin+series+sqrt%28h**2+%2B+x%29+at+x%3D0 */ @@ -2483,7 +2487,7 @@ static inline double vector_norm(Py_ssize_t n, double *vec, double max, int found_nan) { const double T27 = 134217729.0; /* ldexp(1.0, 27)+1.0) */ - double x, csum = 1.0, oldcsum, frac = 0.0, scale; + double x, csum = 1.0, oldcsum, frac = 0.0, frac_lo = 0.0, scale; double t, hi, lo, h; int max_e; Py_ssize_t i; @@ -2528,8 +2532,9 @@ vector_norm(Py_ssize_t n, double *vec, double max, int found_nan) frac += (oldcsum - csum) + x; assert(csum + lo * lo == csum); - frac += lo * lo; + frac_lo += lo * lo; } + frac += frac_lo; h = sqrt(csum - 1.0 + frac); x = h; From 582f13786bb75c73d609790967fea03a5b50148a Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Sun, 30 Aug 2020 18:29:53 +0100 Subject: [PATCH 24/63] bpo-39994: Fix pprint handling of dict subclasses that override __repr__ (GH-21892) Co-authored-by: Palak Kumar Jha --- Lib/pprint.py | 6 --- Lib/test/test_pprint.py | 49 ++++++++++++++++++- Misc/ACKS | 1 + .../2020-08-15-18-17-21.bpo-39994.dOgPOh.rst | 1 + 4 files changed, 50 insertions(+), 7 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2020-08-15-18-17-21.bpo-39994.dOgPOh.rst diff --git a/Lib/pprint.py b/Lib/pprint.py index 7c1118a484b268..213998e3491ef7 100644 --- a/Lib/pprint.py +++ b/Lib/pprint.py @@ -176,12 +176,6 @@ def _format(self, object, stream, indent, allowance, context, level): p(self, object, stream, indent, allowance, context, level + 1) del context[objid] return - elif isinstance(object, dict): - context[objid] = 1 - self._pprint_dict(object, stream, indent, allowance, - context, level + 1) - del context[objid] - return stream.write(rep) _dispatch = {} diff --git a/Lib/test/test_pprint.py b/Lib/test/test_pprint.py index cf3e4f093b16ee..8ee18e8fef84f7 100644 --- a/Lib/test/test_pprint.py +++ b/Lib/test/test_pprint.py @@ -18,6 +18,10 @@ class list3(list): def __repr__(self): return list.__repr__(self) +class list_custom_repr(list): + def __repr__(self): + return '*'*len(list.__repr__(self)) + class tuple2(tuple): pass @@ -25,6 +29,10 @@ class tuple3(tuple): def __repr__(self): return tuple.__repr__(self) +class tuple_custom_repr(tuple): + def __repr__(self): + return '*'*len(tuple.__repr__(self)) + class set2(set): pass @@ -32,6 +40,10 @@ class set3(set): def __repr__(self): return set.__repr__(self) +class set_custom_repr(set): + def __repr__(self): + return '*'*len(set.__repr__(self)) + class frozenset2(frozenset): pass @@ -39,6 +51,10 @@ class frozenset3(frozenset): def __repr__(self): return frozenset.__repr__(self) +class frozenset_custom_repr(frozenset): + def __repr__(self): + return '*'*len(frozenset.__repr__(self)) + class dict2(dict): pass @@ -46,6 +62,10 @@ class dict3(dict): def __repr__(self): return dict.__repr__(self) +class dict_custom_repr(dict): + def __repr__(self): + return '*'*len(dict.__repr__(self)) + class Unorderable: def __repr__(self): return str(id(self)) @@ -155,7 +175,8 @@ def test_unreadable(self): "expected not isreadable for %r" % (unreadable,)) def test_same_as_repr(self): - # Simple objects, small containers and classes that overwrite __repr__ + # Simple objects, small containers and classes that override __repr__ + # to directly call super's __repr__. # For those the result should be the same as repr(). # Ahem. The docs don't say anything about that -- this appears to # be testing an implementation quirk. Starting in Python 2.5, it's @@ -187,6 +208,32 @@ def test_same_as_repr(self): .replace('\n', ' '), native) self.assertEqual(pprint.saferepr(simple), native) + def test_container_repr_override_called(self): + N = 1000 + # Ensure that __repr__ override is called for subclasses of containers + + for cont in (list_custom_repr(), + list_custom_repr([1,2,3]), + list_custom_repr(range(N)), + tuple_custom_repr(), + tuple_custom_repr([1,2,3]), + tuple_custom_repr(range(N)), + set_custom_repr(), + set_custom_repr([1,2,3]), + set_custom_repr(range(N)), + frozenset_custom_repr(), + frozenset_custom_repr([1,2,3]), + frozenset_custom_repr(range(N)), + dict_custom_repr(), + dict_custom_repr({5: 6}), + dict_custom_repr(zip(range(N),range(N))), + ): + native = repr(cont) + expected = '*' * len(native) + self.assertEqual(pprint.pformat(cont), expected) + self.assertEqual(pprint.pformat(cont, width=1, indent=0), expected) + self.assertEqual(pprint.saferepr(cont), expected) + def test_basic_line_wrap(self): # verify basic line-wrapping operation o = {'RPM_cal': 0, diff --git a/Misc/ACKS b/Misc/ACKS index 1599b09c692b75..a2cdeb85040599 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -856,6 +856,7 @@ Per Øyvind Karlsen Anton Kasyanov Lou Kates Makoto Kato +Irit Katriel Hiroaki Kawai Dmitry Kazakov Brian Kearns diff --git a/Misc/NEWS.d/next/Library/2020-08-15-18-17-21.bpo-39994.dOgPOh.rst b/Misc/NEWS.d/next/Library/2020-08-15-18-17-21.bpo-39994.dOgPOh.rst new file mode 100644 index 00000000000000..46876c15ea199c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-08-15-18-17-21.bpo-39994.dOgPOh.rst @@ -0,0 +1 @@ +Fixed pprint's handling of dict subclasses that override __repr__. From 475a5fbb5644ea200c990d85d8c264e78ab6c7ea Mon Sep 17 00:00:00 2001 From: Vinay Sharma Date: Mon, 31 Aug 2020 00:33:11 +0530 Subject: [PATCH 25/63] bpo-41344: Raise ValueError when creating shared memory of size 0 (GH-21556) --- Lib/multiprocessing/shared_memory.py | 2 ++ Lib/test/_test_multiprocessing.py | 12 ++++++++++++ .../Library/2020-07-20-13-27-48.bpo-41344.iKipNd.rst | 1 + 3 files changed, 15 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2020-07-20-13-27-48.bpo-41344.iKipNd.rst diff --git a/Lib/multiprocessing/shared_memory.py b/Lib/multiprocessing/shared_memory.py index a3a5fcf4aba1e7..122b3fcebf3fed 100644 --- a/Lib/multiprocessing/shared_memory.py +++ b/Lib/multiprocessing/shared_memory.py @@ -76,6 +76,8 @@ def __init__(self, name=None, create=False, size=0): raise ValueError("'size' must be a positive integer") if create: self._flags = _O_CREX | os.O_RDWR + if size == 0: + raise ValueError("'size' must be a positive number different from zero") if name is None and not self._flags & os.O_EXCL: raise ValueError("'name' can only be None if create=True") diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index 6a0e1016aff8d0..fd3b4303f034c1 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -3880,6 +3880,18 @@ class OptionalAttachSharedMemory(shared_memory.SharedMemory): sms.close() + # Test creating a shared memory segment with negative size + with self.assertRaises(ValueError): + sms_invalid = shared_memory.SharedMemory(create=True, size=-1) + + # Test creating a shared memory segment with size 0 + with self.assertRaises(ValueError): + sms_invalid = shared_memory.SharedMemory(create=True, size=0) + + # Test creating a shared memory segment without size argument + with self.assertRaises(ValueError): + sms_invalid = shared_memory.SharedMemory(create=True) + def test_shared_memory_across_processes(self): # bpo-40135: don't define shared memory block's name in case of # the failure when we run multiprocessing tests in parallel. diff --git a/Misc/NEWS.d/next/Library/2020-07-20-13-27-48.bpo-41344.iKipNd.rst b/Misc/NEWS.d/next/Library/2020-07-20-13-27-48.bpo-41344.iKipNd.rst new file mode 100644 index 00000000000000..475bc9bddb0d54 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-07-20-13-27-48.bpo-41344.iKipNd.rst @@ -0,0 +1 @@ +Prevent creating :class:`shared_memory.SharedMemory` objects with :code:`size=0`. From c3a651ad2544d7d1be389b63e9a4a58a92a31623 Mon Sep 17 00:00:00 2001 From: Andre Delfino Date: Sun, 30 Aug 2020 17:36:58 -0300 Subject: [PATCH 26/63] [doc] Fix markup in logging (GH-22008) --- Doc/library/logging.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index 3ff67f76cc3c5a..a446c80ece6048 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -1222,7 +1222,7 @@ functions. | | opening the output file. If not specified, | | | the value 'backslashreplace' is used. Note | | | that if ``None`` is specified, it will be | - | | passed as such to func:`open`, which means | + | | passed as such to :func:`open`, which means | | | that it will be treated the same as passing | | | 'errors'. | +--------------+---------------------------------------------+ From ea5a6363c3f8cc90b7c0cc573922b10f296073b6 Mon Sep 17 00:00:00 2001 From: Ben Darnell Date: Mon, 31 Aug 2020 15:57:52 -0400 Subject: [PATCH 27/63] bpo-39010: Fix errors logged on proactor loop restart (#22017) Stopping and restarting a proactor event loop on windows can lead to spurious errors logged (ConnectionResetError while reading from the self pipe). This fixes the issue by ensuring that we don't attempt to start multiple copies of the self-pipe reading loop. --- Lib/asyncio/proactor_events.py | 8 ++++++++ Lib/asyncio/windows_events.py | 8 ++++++-- Lib/test/test_asyncio/test_proactor_events.py | 1 + Lib/test/test_asyncio/test_windows_events.py | 20 +++++++++++++++++++ .../2020-08-30-10-24-26.bpo-39010._mzXJW.rst | 2 ++ 5 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2020-08-30-10-24-26.bpo-39010._mzXJW.rst diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py index d0b7100f5e0563..4670bd683ab32c 100644 --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -768,6 +768,14 @@ def _loop_self_reading(self, f=None): try: if f is not None: f.result() # may raise + if self._self_reading_future is not f: + # When we scheduled this Future, we assigned it to + # _self_reading_future. If it's not there now, something has + # tried to cancel the loop while this callback was still in the + # queue (see windows_events.ProactorEventLoop.run_forever). In + # that case stop here instead of continuing to schedule a new + # iteration. + return f = self._proactor.recv(self._ssock, 4096) except exceptions.CancelledError: # _close_self_pipe() has been called, stop waiting for data diff --git a/Lib/asyncio/windows_events.py b/Lib/asyncio/windows_events.py index a6759b78bd801f..5e7cd795895d65 100644 --- a/Lib/asyncio/windows_events.py +++ b/Lib/asyncio/windows_events.py @@ -318,8 +318,12 @@ def run_forever(self): if self._self_reading_future is not None: ov = self._self_reading_future._ov self._self_reading_future.cancel() - # self_reading_future was just cancelled so it will never be signalled - # Unregister it otherwise IocpProactor.close will wait for it forever + # self_reading_future was just cancelled so if it hasn't been + # finished yet, it never will be (it's possible that it has + # already finished and its callback is waiting in the queue, + # where it could still happen if the event loop is restarted). + # Unregister it otherwise IocpProactor.close will wait for it + # forever if ov is not None: self._proactor._unregister(ov) self._self_reading_future = None diff --git a/Lib/test/test_asyncio/test_proactor_events.py b/Lib/test/test_asyncio/test_proactor_events.py index d0ab38743ecd1f..4c8906d531ce5c 100644 --- a/Lib/test/test_asyncio/test_proactor_events.py +++ b/Lib/test/test_asyncio/test_proactor_events.py @@ -753,6 +753,7 @@ def test_loop_self_reading(self): def test_loop_self_reading_fut(self): fut = mock.Mock() + self.loop._self_reading_future = fut self.loop._loop_self_reading(fut) self.assertTrue(fut.result.called) self.proactor.recv.assert_called_with(self.ssock, 4096) diff --git a/Lib/test/test_asyncio/test_windows_events.py b/Lib/test/test_asyncio/test_windows_events.py index 6b005702c9be73..33388a87d48f3f 100644 --- a/Lib/test/test_asyncio/test_windows_events.py +++ b/Lib/test/test_asyncio/test_windows_events.py @@ -211,6 +211,26 @@ def test_wait_for_handle_cancel(self): fut.cancel() fut.cancel() + def test_read_self_pipe_restart(self): + # Regression test for https://bugs.python.org/issue39010 + # Previously, restarting a proactor event loop in certain states + # would lead to spurious ConnectionResetErrors being logged. + self.loop.call_exception_handler = mock.Mock() + # Start an operation in another thread so that the self-pipe is used. + # This is theoretically timing-dependent (the task in the executor + # must complete before our start/stop cycles), but in practice it + # seems to work every time. + f = self.loop.run_in_executor(None, lambda: None) + self.loop.stop() + self.loop.run_forever() + self.loop.stop() + self.loop.run_forever() + # If we don't wait for f to complete here, we may get another + # warning logged about a thread that didn't shut down cleanly. + self.loop.run_until_complete(f) + self.loop.close() + self.assertFalse(self.loop.call_exception_handler.called) + class WinPolicyTests(test_utils.TestCase): diff --git a/Misc/NEWS.d/next/Library/2020-08-30-10-24-26.bpo-39010._mzXJW.rst b/Misc/NEWS.d/next/Library/2020-08-30-10-24-26.bpo-39010._mzXJW.rst new file mode 100644 index 00000000000000..0d9015b490e4cb --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-08-30-10-24-26.bpo-39010._mzXJW.rst @@ -0,0 +1,2 @@ +Restarting a ``ProactorEventLoop`` on Windows no longer logs spurious +``ConnectionResetErrors``. From 3584d4b64a5373440f78237eac734831cfd83f79 Mon Sep 17 00:00:00 2001 From: Andre Delfino Date: Tue, 1 Sep 2020 03:07:29 -0300 Subject: [PATCH 28/63] [doc] Document VIRTUAL_ENV environment variable (GH-21970) --- Doc/using/venv-create.inc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Doc/using/venv-create.inc b/Doc/using/venv-create.inc index c8f6e8f87d5674..8f850a74d413ce 100644 --- a/Doc/using/venv-create.inc +++ b/Doc/using/venv-create.inc @@ -126,6 +126,10 @@ directory containing the virtual environment): | | PowerShell | PS C:\\> \\Scripts\\Activate.ps1 | +-------------+-----------------+-----------------------------------------+ +When a virtual environment is active, the :envvar:`VIRTUAL_ENV` environment +variable is set to the path of the virtual environment. This can be used to +check if one is running inside a virtual environment. + You don't specifically *need* to activate an environment; activation just prepends the virtual environment's binary directory to your path, so that "python" invokes the virtual environment's Python interpreter and you can run From a4c4e17f959621ab00a98086af1704fb0c896466 Mon Sep 17 00:00:00 2001 From: Ned Deily Date: Tue, 1 Sep 2020 05:40:27 -0400 Subject: [PATCH 29/63] bpo-41685: Temporarily pin setuptools to 49.2.1 in Docs venv. (GH-22038) See https://github.com/pypa/setuptools/pull/2361 --- Doc/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Doc/Makefile b/Doc/Makefile index b8ca1edfbc60a5..87d5d07665c863 100644 --- a/Doc/Makefile +++ b/Doc/Makefile @@ -142,7 +142,8 @@ clean: venv: $(PYTHON) -m venv $(VENVDIR) - $(VENVDIR)/bin/python3 -m pip install -U pip setuptools +# $(VENVDIR)/bin/python3 -m pip install -U pip setuptools + $(VENVDIR)/bin/python3 -m pip install -U pip setuptools==49.2.1 $(VENVDIR)/bin/python3 -m pip install -U Sphinx==2.3.1 blurb python-docs-theme @echo "The venv has been created in the $(VENVDIR) directory" From f5a16b4dbf62cb9b48c42098bd5a8cfa665456c3 Mon Sep 17 00:00:00 2001 From: Andre Delfino Date: Tue, 1 Sep 2020 09:59:46 -0300 Subject: [PATCH 30/63] [doc] Add link to FileHandler in logging (GH-21940) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Andrés Delfino --- Doc/library/logging.rst | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index a446c80ece6048..19691d50937a71 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -1166,9 +1166,9 @@ functions. +--------------+---------------------------------------------+ | Format | Description | +==============+=============================================+ - | *filename* | Specifies that a FileHandler be created, | - | | using the specified filename, rather than a | - | | StreamHandler. | + | *filename* | Specifies that a :class:`FileHandler` be | + | | created, using the specified filename, | + | | rather than a :class:`StreamHandler`. | +--------------+---------------------------------------------+ | *filemode* | If *filename* is specified, open the file | | | in this :ref:`mode `. Defaults | @@ -1192,9 +1192,10 @@ functions. | | :ref:`level `. | +--------------+---------------------------------------------+ | *stream* | Use the specified stream to initialize the | - | | StreamHandler. Note that this argument is | - | | incompatible with *filename* - if both | - | | are present, a ``ValueError`` is raised. | + | | :class:`StreamHandler`. Note that this | + | | argument is incompatible with *filename* - | + | | if both are present, a ``ValueError`` is | + | | raised. | +--------------+---------------------------------------------+ | *handlers* | If specified, this should be an iterable of | | | already created handlers to add to the root | @@ -1213,18 +1214,18 @@ functions. +--------------+---------------------------------------------+ | *encoding* | If this keyword argument is specified along | | | with *filename*, its value is used when the | - | | FileHandler is created, and thus used when | - | | opening the output file. | + | | :class:`FileHandler` is created, and thus | + | | used when opening the output file. | +--------------+---------------------------------------------+ | *errors* | If this keyword argument is specified along | | | with *filename*, its value is used when the | - | | FileHandler is created, and thus used when | - | | opening the output file. If not specified, | - | | the value 'backslashreplace' is used. Note | - | | that if ``None`` is specified, it will be | - | | passed as such to :func:`open`, which means | - | | that it will be treated the same as passing | - | | 'errors'. | + | | :class:`FileHandler` is created, and thus | + | | used when opening the output file. If not | + | | specified, the value 'backslashreplace' is | + | | used. Note that if ``None`` is specified, | + | | it will be passed as such to :func:`open`, | + | | which means that it will be treated the | + | | same as passing 'errors'. | +--------------+---------------------------------------------+ .. versionchanged:: 3.2 From 0d6aa7f0ee38eb453bc8f73bf4830e6172be2f35 Mon Sep 17 00:00:00 2001 From: han-solo Date: Tue, 1 Sep 2020 10:34:29 -0400 Subject: [PATCH 31/63] bpo-41681: Fix for `f-string/str.format` error description when using 2 `,` in format specifier (GH-22036) * Fixed `f-string/str.format` error description when using two `,` in format specifier. Co-authored-by: millefalcon --- Lib/test/test_format.py | 20 +++++++++++++++++++ Lib/test/test_fstring.py | 20 +++++++++++++++++++ .../2020-08-31-17-49-02.bpo-41681.3-VJiH.rst | 2 ++ Python/formatter_unicode.c | 6 ++++-- 4 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2020-08-31-17-49-02.bpo-41681.3-VJiH.rst diff --git a/Lib/test/test_format.py b/Lib/test/test_format.py index e9e5bb9cf00a62..dff8c690321878 100644 --- a/Lib/test/test_format.py +++ b/Lib/test/test_format.py @@ -1,6 +1,7 @@ from test.support import verbose, TestFailed import locale import sys +import re import test.support as support import unittest @@ -495,6 +496,25 @@ def test_g_format_has_no_trailing_zeros(self): self.assertEqual(format(12300050.0, ".6g"), "1.23e+07") self.assertEqual(format(12300050.0, "#.6g"), "1.23000e+07") + def test_with_two_commas_in_format_specifier(self): + error_msg = re.escape("Cannot specify ',' with ','.") + with self.assertRaisesRegex(ValueError, error_msg): + '{:,,}'.format(1) + + def test_with_two_underscore_in_format_specifier(self): + error_msg = re.escape("Cannot specify '_' with '_'.") + with self.assertRaisesRegex(ValueError, error_msg): + '{:__}'.format(1) + + def test_with_a_commas_and_an_underscore_in_format_specifier(self): + error_msg = re.escape("Cannot specify both ',' and '_'.") + with self.assertRaisesRegex(ValueError, error_msg): + '{:,_}'.format(1) + + def test_with_an_underscore_and_a_comma_in_format_specifier(self): + error_msg = re.escape("Cannot specify both ',' and '_'.") + with self.assertRaisesRegex(ValueError, error_msg): + '{:,_}'.format(1) if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_fstring.py b/Lib/test/test_fstring.py index 35a62a0632e2e6..b9bede0d9b800e 100644 --- a/Lib/test/test_fstring.py +++ b/Lib/test/test_fstring.py @@ -9,6 +9,7 @@ import ast import os +import re import types import decimal import unittest @@ -1198,6 +1199,25 @@ def test_invalid_syntax_error_message(self): with self.assertRaisesRegex(SyntaxError, "f-string: invalid syntax"): compile("f'{a $ b}'", "?", "exec") + def test_with_two_commas_in_format_specifier(self): + error_msg = re.escape("Cannot specify ',' with ','.") + with self.assertRaisesRegex(ValueError, error_msg): + f'{1:,,}' + + def test_with_two_underscore_in_format_specifier(self): + error_msg = re.escape("Cannot specify '_' with '_'.") + with self.assertRaisesRegex(ValueError, error_msg): + f'{1:__}' + + def test_with_a_commas_and_an_underscore_in_format_specifier(self): + error_msg = re.escape("Cannot specify both ',' and '_'.") + with self.assertRaisesRegex(ValueError, error_msg): + f'{1:,_}' + + def test_with_an_underscore_and_a_comma_in_format_specifier(self): + error_msg = re.escape("Cannot specify both ',' and '_'.") + with self.assertRaisesRegex(ValueError, error_msg): + f'{1:,_}' if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-08-31-17-49-02.bpo-41681.3-VJiH.rst b/Misc/NEWS.d/next/Core and Builtins/2020-08-31-17-49-02.bpo-41681.3-VJiH.rst new file mode 100644 index 00000000000000..ed557f92d85cac --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-08-31-17-49-02.bpo-41681.3-VJiH.rst @@ -0,0 +1,2 @@ +Fixes the wrong error description in the error raised by using 2 `,` in +format string in f-string and :meth:`str.format`. diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c index 74638ca2237729..ed95f267d476c7 100644 --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -252,8 +252,10 @@ parse_internal_render_format_spec(PyObject *format_spec, ++pos; } if (end-pos && READ_spec(pos) == ',') { - invalid_comma_and_underscore(); - return 0; + if (format->thousands_separators == LT_UNDERSCORE_LOCALE) { + invalid_comma_and_underscore(); + return 0; + } } /* Parse field precision */ From e6905e4c82cc05897dc1bf5ab2b5b94b2b043a7f Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 1 Sep 2020 18:25:14 +0200 Subject: [PATCH 32/63] bpo-41617: Fix pycore_bitutils.h to support clang 3.0 (GH-22042) __builtin_bswap16() is not available in LLVM clang 3.0. --- Include/internal/pycore_bitutils.h | 10 ++++++---- .../Build/2020-08-24-18-34-01.bpo-41617.sKKXz7.rst | 2 ++ 2 files changed, 8 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Build/2020-08-24-18-34-01.bpo-41617.sKKXz7.rst diff --git a/Include/internal/pycore_bitutils.h b/Include/internal/pycore_bitutils.h index 0bd3270fe82e5c..1602fc68d94074 100644 --- a/Include/internal/pycore_bitutils.h +++ b/Include/internal/pycore_bitutils.h @@ -17,10 +17,12 @@ extern "C" { # error "this header requires Py_BUILD_CORE define" #endif -#if defined(__clang__) || \ - (defined(__GNUC__) && \ - ((__GNUC__ >= 5) || (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8))) - /* __builtin_bswap16() is available since GCC 4.8, +#if ((defined(__GNUC__) \ + && ((__GNUC__ >= 5) || (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8))) \ + || (defined(__clang__) \ + && (__clang_major__ >= 4 \ + || (__clang_major__ == 3 && __clang_minor__ >= 2)))) + /* __builtin_bswap16() is available since GCC 4.8 and clang 3.2, __builtin_bswap32() is available since GCC 4.3, __builtin_bswap64() is available since GCC 4.3. */ # define _PY_HAVE_BUILTIN_BSWAP diff --git a/Misc/NEWS.d/next/Build/2020-08-24-18-34-01.bpo-41617.sKKXz7.rst b/Misc/NEWS.d/next/Build/2020-08-24-18-34-01.bpo-41617.sKKXz7.rst new file mode 100644 index 00000000000000..715eadbee896f1 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2020-08-24-18-34-01.bpo-41617.sKKXz7.rst @@ -0,0 +1,2 @@ +Fix ``pycore_bitutils.h`` header file to support old clang versions: +``__builtin_bswap16()`` is not available in LLVM clang 3.0. From 6844b56176c41f0a0e25fcd4fef5463bcdbc7d7c Mon Sep 17 00:00:00 2001 From: Marek Madejski Date: Tue, 1 Sep 2020 18:42:41 +0200 Subject: [PATCH 33/63] bpo-41528: Use math module in turtle (GH-21837) Use angle-related functions from math module instead of reinventing the wheel. --- Lib/turtle.py | 18 +++++++++--------- .../2020-08-12-07-43-31.bpo-41528.bu83oD.rst | 1 + 2 files changed, 10 insertions(+), 9 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2020-08-12-07-43-31.bpo-41528.bu83oD.rst diff --git a/Lib/turtle.py b/Lib/turtle.py index ee67a351b54f19..92d4e5dda9c2db 100644 --- a/Lib/turtle.py +++ b/Lib/turtle.py @@ -263,12 +263,12 @@ def __sub__(self, other): def __neg__(self): return Vec2D(-self[0], -self[1]) def __abs__(self): - return (self[0]**2 + self[1]**2)**0.5 + return math.hypot(*self) def rotate(self, angle): """rotate self counterclockwise by angle """ perp = Vec2D(-self[1], self[0]) - angle = angle * math.pi / 180.0 + angle = math.radians(angle) c, s = math.cos(angle), math.sin(angle) return Vec2D(self[0]*c+perp[0]*s, self[1]*c+perp[1]*s) def __getnewargs__(self): @@ -1597,7 +1597,7 @@ def radians(self): >>> turtle.heading() 1.5707963267948966 """ - self._setDegreesPerAU(2*math.pi) + self._setDegreesPerAU(math.tau) def _go(self, distance): """move turtle forward by specified distance""" @@ -1888,7 +1888,7 @@ def towards(self, x, y=None): elif isinstance(x, TNavigator): pos = x._position x, y = pos - self._position - result = round(math.atan2(y, x)*180.0/math.pi, 10) % 360.0 + result = round(math.degrees(math.atan2(y, x)), 10) % 360.0 result /= self._degreesPerAU return (self._angleOffset + self._angleOrient*result) % self._fullcircle @@ -1903,7 +1903,7 @@ def heading(self): 67.0 """ x, y = self._orient - result = round(math.atan2(y, x)*180.0/math.pi, 10) % 360.0 + result = round(math.degrees(math.atan2(y, x)), 10) % 360.0 result /= self._degreesPerAU return (self._angleOffset + self._angleOrient*result) % self._fullcircle @@ -1976,7 +1976,7 @@ def circle(self, radius, extent = None, steps = None): steps = 1+int(min(11+abs(radius)/6.0, 59.0)*frac) w = 1.0 * extent / steps w2 = 0.5 * w - l = 2.0 * radius * math.sin(w2*math.pi/180.0*self._degreesPerAU) + l = 2.0 * radius * math.sin(math.radians(w2)*self._degreesPerAU) if radius < 0: l, w, w2 = -l, -w, -w2 tr = self._tracer() @@ -2861,7 +2861,7 @@ def settiltangle(self, angle): >>> turtle.fd(50) """ tilt = -angle * self._degreesPerAU * self._angleOrient - tilt = (tilt * math.pi / 180.0) % (2*math.pi) + tilt = math.radians(tilt) % math.tau self.pen(resizemode="user", tilt=tilt) def tiltangle(self, angle=None): @@ -2885,7 +2885,7 @@ def tiltangle(self, angle=None): >>> turtle.tiltangle() """ if angle is None: - tilt = -self._tilt * (180.0/math.pi) * self._angleOrient + tilt = -math.degrees(self._tilt) * self._angleOrient return (tilt / self._degreesPerAU) % self._fullcircle else: self.settiltangle(angle) @@ -2939,7 +2939,7 @@ def shapetransform(self, t11=None, t12=None, t21=None, t22=None): if t11 * t22 - t12 * t21 == 0: raise TurtleGraphicsError("Bad shape transform matrix: must not be singular") self._shapetrafo = (m11, m12, m21, m22) - alfa = math.atan2(-m21, m11) % (2 * math.pi) + alfa = math.atan2(-m21, m11) % math.tau sa, ca = math.sin(alfa), math.cos(alfa) a11, a12, a21, a22 = (ca*m11 - sa*m21, ca*m12 - sa*m22, sa*m11 + ca*m21, sa*m12 + ca*m22) diff --git a/Misc/NEWS.d/next/Library/2020-08-12-07-43-31.bpo-41528.bu83oD.rst b/Misc/NEWS.d/next/Library/2020-08-12-07-43-31.bpo-41528.bu83oD.rst new file mode 100644 index 00000000000000..a4ba57c2438ed6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-08-12-07-43-31.bpo-41528.bu83oD.rst @@ -0,0 +1 @@ +turtle uses math module functions to convert degrees to radians and vice versa and to calculate vector norm \ No newline at end of file From 9b648a95ccb4c3b14f1e87158f5c9f5dbb2f62c0 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Tue, 1 Sep 2020 19:39:46 +0100 Subject: [PATCH 34/63] bpo-41654: Fix deallocator of MemoryError to account for subclasses (GH-22020) When allocating MemoryError classes, there is some logic to use pre-allocated instances in a freelist only if the type that is being allocated is not a subclass of MemoryError. Unfortunately in the destructor this logic is not present so the freelist is altered even with subclasses of MemoryError. --- Lib/test/test_exceptions.py | 31 +++++++++++++++++++ .../2020-08-30-20-38-33.bpo-41654.HtnhAM.rst | 2 ++ Objects/exceptions.c | 14 +++++++-- 3 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2020-08-30-20-38-33.bpo-41654.HtnhAM.rst diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 2ffe8caa03f812..1ec446887770ea 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -1,6 +1,7 @@ # Python test set -- part 5, built-in exceptions import copy +import gc import os import sys import unittest @@ -1330,6 +1331,36 @@ def test_assert_shadowing(self): del AssertionError self.fail('Expected exception') + def test_memory_error_subclasses(self): + # bpo-41654: MemoryError instances use a freelist of objects that are + # linked using the 'dict' attribute when they are inactive/dead. + # Subclasses of MemoryError should not participate in the freelist + # schema. This test creates a MemoryError object and keeps it alive + # (therefore advancing the freelist) and then it creates and destroys a + # subclass object. Finally, it checks that creating a new MemoryError + # succeeds, proving that the freelist is not corrupted. + + class TestException(MemoryError): + pass + + try: + raise MemoryError + except MemoryError as exc: + inst = exc + + try: + raise TestException + except Exception: + pass + + for _ in range(10): + try: + raise MemoryError + except MemoryError as exc: + pass + + gc_collect() + class ImportErrorTests(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-08-30-20-38-33.bpo-41654.HtnhAM.rst b/Misc/NEWS.d/next/Core and Builtins/2020-08-30-20-38-33.bpo-41654.HtnhAM.rst new file mode 100644 index 00000000000000..e05c3133e12625 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-08-30-20-38-33.bpo-41654.HtnhAM.rst @@ -0,0 +1,2 @@ +Fix a crash that occurred when destroying subclasses of +:class:`MemoryError`. Patch by Pablo Galindo. diff --git a/Objects/exceptions.c b/Objects/exceptions.c index 1195ba17922dd7..b08cbdd6aed357 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -2286,8 +2286,11 @@ MemoryError_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyBaseExceptionObject *self; - if (type != (PyTypeObject *) PyExc_MemoryError) + /* If this is a subclass of MemoryError, don't use the freelist + * and just return a fresh object */ + if (type != (PyTypeObject *) PyExc_MemoryError) { return BaseException_new(type, args, kwds); + } struct _Py_exc_state *state = get_exc_state(); if (state->memerrors_freelist == NULL) { @@ -2313,9 +2316,16 @@ MemoryError_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static void MemoryError_dealloc(PyBaseExceptionObject *self) { - _PyObject_GC_UNTRACK(self); BaseException_clear(self); + /* If this is a subclass of MemoryError, we don't need to + * do anything in the free-list*/ + if (!Py_IS_TYPE(self, (PyTypeObject *) PyExc_MemoryError)) { + return Py_TYPE(self)->tp_free((PyObject *)self); + } + + _PyObject_GC_UNTRACK(self); + struct _Py_exc_state *state = get_exc_state(); if (state->memerrors_numfree >= MEMERRORS_SAVE) { Py_TYPE(self)->tp_free((PyObject *)self); From 17dc1b789ecc33b4a254eb3b799085f4b3624ca5 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Tue, 1 Sep 2020 14:18:07 -0700 Subject: [PATCH 35/63] bpo-39349: Add cancel_futures to Executor.shutdown base class (GH-22023) * Add cancel_futures parameter to the Executor base class, since it was missed in the original PR (https://github.com/python/cpython/pull/18057) that added cancel_futures. --- Lib/concurrent/futures/_base.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Lib/concurrent/futures/_base.py b/Lib/concurrent/futures/_base.py index bf546f8ae1d1cc..00eb54881f2958 100644 --- a/Lib/concurrent/futures/_base.py +++ b/Lib/concurrent/futures/_base.py @@ -605,7 +605,7 @@ def result_iterator(): future.cancel() return result_iterator() - def shutdown(self, wait=True): + def shutdown(self, wait=True, *, cancel_futures=False): """Clean-up the resources associated with the Executor. It is safe to call this method several times. Otherwise, no other @@ -615,6 +615,9 @@ def shutdown(self, wait=True): wait: If True then shutdown will not return until all running futures have finished executing and the resources used by the executor have been reclaimed. + cancel_futures: If True then shutdown will cancel all pending + futures. Futures that are completed or running will not be + cancelled. """ pass From 700fa1b836f315048e8b89ede5018a0c0a213946 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 1 Sep 2020 20:36:42 -0500 Subject: [PATCH 36/63] Note the buffer slots can be set with PyType_Spec with the unlimited API. (GH-22031) Follow up to f7c4e236429606e1c982cacf24e10fc86ef4462f. --- Doc/c-api/type.rst | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Doc/c-api/type.rst b/Doc/c-api/type.rst index 7309d7ee2cd398..73f26875d8194a 100644 --- a/Doc/c-api/type.rst +++ b/Doc/c-api/type.rst @@ -225,7 +225,8 @@ The following functions and structs are used to create * ``Py_nb_add`` to set :c:member:`PyNumberMethods.nb_add` * ``Py_sq_length`` to set :c:member:`PySequenceMethods.sq_length` - The following fields cannot be set using :c:type:`PyType_Spec` and :c:type:`PyType_Slot`: + The following fields cannot be set at all using :c:type:`PyType_Spec` and + :c:type:`PyType_Slot`: * :c:member:`~PyTypeObject.tp_dict` * :c:member:`~PyTypeObject.tp_mro` @@ -239,6 +240,10 @@ The following functions and structs are used to create (see :ref:`PyMemberDef `) * :c:member:`~PyTypeObject.tp_vectorcall_offset` (see :ref:`PyMemberDef `) + + The following fields cannot be set using :c:type:`PyType_Spec` and + :c:type:`PyType_Slot` under the limited API: + * :c:member:`~PyBufferProcs.bf_getbuffer` * :c:member:`~PyBufferProcs.bf_releasebuffer` @@ -246,6 +251,10 @@ The following functions and structs are used to create To avoid issues, use the *bases* argument of :py:func:`PyType_FromSpecWithBases` instead. + .. versionchanged:: 3.9 + + Slots in :c:type:`PyBufferProcs` in may be set in the unlimited API. + .. c:member:: void *PyType_Slot.pfunc The desired value of the slot. In most cases, this is a pointer From dea82b67315a6b873f7d4e558dd00a851137dcbb Mon Sep 17 00:00:00 2001 From: Andre Delfino Date: Wed, 2 Sep 2020 00:21:12 -0300 Subject: [PATCH 37/63] [doc] Remove references to PyChecker. (GH-22011) --- Doc/faq/design.rst | 3 +-- Doc/faq/programming.rst | 16 ++++------------ 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/Doc/faq/design.rst b/Doc/faq/design.rst index 4e3cc575ee1964..8cf271c3024084 100644 --- a/Doc/faq/design.rst +++ b/Doc/faq/design.rst @@ -573,8 +573,7 @@ whether an instance or a class implements a particular ABC. The :class:`~collections.abc.MutableMapping`. For Python, many of the advantages of interface specifications can be obtained -by an appropriate test discipline for components. There is also a tool, -PyChecker, which can be used to find problems due to subclassing. +by an appropriate test discipline for components. A good test suite for a module can both provide a regression test and serve as a module interface specification and a set of examples. Many Python modules can diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst index 0731e92f6dbc60..d6a2f2cfc67eed 100644 --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -57,22 +57,14 @@ They include: * PyCharm (https://www.jetbrains.com/pycharm/) -Is there a tool to help find bugs or perform static analysis? +Are there tools to help find bugs or perform static analysis? ------------------------------------------------------------- Yes. -PyChecker is a static analysis tool that finds bugs in Python source code and -warns about code complexity and style. You can get PyChecker from -http://pychecker.sourceforge.net/. - -`Pylint `_ is another tool that checks -if a module satisfies a coding standard, and also makes it possible to write -plug-ins to add a custom feature. In addition to the bug checking that -PyChecker performs, Pylint offers some additional features such as checking line -length, whether variable names are well-formed according to your coding -standard, whether declared interfaces are fully implemented, and more. -https://docs.pylint.org/ provides a full list of Pylint's features. +`Pylint `_ and +`Pyflakes `_ do basic checking that will +help you catch bugs sooner. Static type checkers such as `Mypy `_, `Pyre `_, and From 1d25f5bf7b795b47e753aca56d7579d4ad7ee468 Mon Sep 17 00:00:00 2001 From: Andre Delfino Date: Wed, 2 Sep 2020 00:22:55 -0300 Subject: [PATCH 38/63] Remove reference to Boa Constructor. (GH-22012) --- Doc/faq/programming.rst | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst index d6a2f2cfc67eed..66d210a55fac7e 100644 --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -35,12 +35,6 @@ for Windows Extensions `__ project an as a part of the ActivePython distribution (see https://www.activestate.com/activepython\ ). -`Boa Constructor `_ is an IDE and GUI -builder that uses wxWidgets. It offers visual frame creation and manipulation, -an object inspector, many views on the source like object browsers, inheritance -hierarchies, doc string generated html documentation, an advanced debugger, -integrated help, and Zope support. - `Eric `_ is an IDE built on PyQt and the Scintilla editing component. From 5b24d1592a990ad7cf81cd1498d255bad41a0b14 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Tue, 1 Sep 2020 22:00:50 -0700 Subject: [PATCH 39/63] Improve hypot() accuracy with three separate accumulators (GH-22032) --- Modules/mathmodule.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Modules/mathmodule.c b/Modules/mathmodule.c index 6621951ee97d2b..d227a5d15dca2a 100644 --- a/Modules/mathmodule.c +++ b/Modules/mathmodule.c @@ -2456,7 +2456,7 @@ Given that csum >= 1.0, we have: Since lo**2 is less than 1/2 ulp(csum), we have csum+lo*lo == csum. To minimize loss of information during the accumulation of fractional -values, the lo**2 term has a separate accumulator. +values, each term has a separate accumulator. The square root differential correction is needed because a correctly rounded square root of a correctly rounded sum of @@ -2487,7 +2487,7 @@ static inline double vector_norm(Py_ssize_t n, double *vec, double max, int found_nan) { const double T27 = 134217729.0; /* ldexp(1.0, 27)+1.0) */ - double x, csum = 1.0, oldcsum, frac = 0.0, frac_lo = 0.0, scale; + double x, csum = 1.0, oldcsum, scale, frac=0.0, frac_mid=0.0, frac_lo=0.0; double t, hi, lo, h; int max_e; Py_ssize_t i; @@ -2529,12 +2529,12 @@ vector_norm(Py_ssize_t n, double *vec, double max, int found_nan) assert(fabs(csum) >= fabs(x)); oldcsum = csum; csum += x; - frac += (oldcsum - csum) + x; + frac_mid += (oldcsum - csum) + x; assert(csum + lo * lo == csum); frac_lo += lo * lo; } - frac += frac_lo; + frac += frac_lo + frac_mid; h = sqrt(csum - 1.0 + frac); x = h; From 749ed85e4446f548e22934931241f644a33d81ce Mon Sep 17 00:00:00 2001 From: han-solo Date: Wed, 2 Sep 2020 04:56:37 -0400 Subject: [PATCH 40/63] Fixed mistake in test for f-string error description (GH-22036) (GH-22059) --- Lib/test/test_format.py | 2 +- Lib/test/test_fstring.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_format.py b/Lib/test/test_format.py index dff8c690321878..d2744cdfdca60e 100644 --- a/Lib/test/test_format.py +++ b/Lib/test/test_format.py @@ -514,7 +514,7 @@ def test_with_a_commas_and_an_underscore_in_format_specifier(self): def test_with_an_underscore_and_a_comma_in_format_specifier(self): error_msg = re.escape("Cannot specify both ',' and '_'.") with self.assertRaisesRegex(ValueError, error_msg): - '{:,_}'.format(1) + '{:_,}'.format(1) if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_fstring.py b/Lib/test/test_fstring.py index b9bede0d9b800e..b53661aa0a46fc 100644 --- a/Lib/test/test_fstring.py +++ b/Lib/test/test_fstring.py @@ -1217,7 +1217,7 @@ def test_with_a_commas_and_an_underscore_in_format_specifier(self): def test_with_an_underscore_and_a_comma_in_format_specifier(self): error_msg = re.escape("Cannot specify both ',' and '_'.") with self.assertRaisesRegex(ValueError, error_msg): - f'{1:,_}' + f'{1:_,}' if __name__ == '__main__': unittest.main() From a7f026870d2dab7015a94e287bec6dd46cdbf604 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Wed, 2 Sep 2020 04:45:13 -0500 Subject: [PATCH 41/63] bpo-1635741: Port _blake2 module to multi-phase init (GH-21856) Port the _blake2 extension module to the multi-phase initialization API (PEP 489). --- ...2020-08-13-07-18-05.bpo-1635741.FC13e7.rst | 1 + Modules/_blake2/blake2b_impl.c | 57 +++------ Modules/_blake2/blake2module.c | 121 ++++++++++++------ Modules/_blake2/blake2s_impl.c | 58 +++------ 4 files changed, 119 insertions(+), 118 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2020-08-13-07-18-05.bpo-1635741.FC13e7.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-08-13-07-18-05.bpo-1635741.FC13e7.rst b/Misc/NEWS.d/next/Core and Builtins/2020-08-13-07-18-05.bpo-1635741.FC13e7.rst new file mode 100644 index 00000000000000..cdfee874095fe5 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-08-13-07-18-05.bpo-1635741.FC13e7.rst @@ -0,0 +1 @@ +Port the :mod:`_blake2` extension module to the multi-phase initialization API (:pep:`489`). diff --git a/Modules/_blake2/blake2b_impl.c b/Modules/_blake2/blake2b_impl.c index 7fb1296f8b2b90..8e1acce56b1d29 100644 --- a/Modules/_blake2/blake2b_impl.c +++ b/Modules/_blake2/blake2b_impl.c @@ -34,7 +34,7 @@ #endif -extern PyTypeObject PyBlake2_BLAKE2bType; +extern PyType_Spec blake2b_type_spec; typedef struct { PyObject_HEAD @@ -391,47 +391,24 @@ py_blake2b_dealloc(PyObject *self) PyThread_free_lock(obj->lock); obj->lock = NULL; } + + PyTypeObject *type = Py_TYPE(self); PyObject_Del(self); + Py_DECREF(type); } +static PyType_Slot blake2b_type_slots[] = { + {Py_tp_dealloc, py_blake2b_dealloc}, + {Py_tp_doc, (char *)py_blake2b_new__doc__}, + {Py_tp_methods, py_blake2b_methods}, + {Py_tp_getset, py_blake2b_getsetters}, + {Py_tp_new, py_blake2b_new}, + {0,0} +}; -PyTypeObject PyBlake2_BLAKE2bType = { - PyVarObject_HEAD_INIT(NULL, 0) - "_blake2.blake2b", /* tp_name */ - sizeof(BLAKE2bObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - py_blake2b_dealloc, /* tp_dealloc */ - 0, /*tp_vectorcall_offset*/ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - py_blake2b_new__doc__, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - py_blake2b_methods, /* tp_methods */ - 0, /* tp_members */ - py_blake2b_getsetters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - py_blake2b_new, /* tp_new */ +PyType_Spec blake2b_type_spec = { + .name = "_blake2.blake2b", + .basicsize = sizeof(BLAKE2bObject), + .flags = Py_TPFLAGS_DEFAULT, + .slots = blake2b_type_slots }; diff --git a/Modules/_blake2/blake2module.c b/Modules/_blake2/blake2module.c index ff142c9f3ed330..631de2cc0abc74 100644 --- a/Modules/_blake2/blake2module.c +++ b/Modules/_blake2/blake2module.c @@ -12,62 +12,81 @@ #include "impl/blake2.h" -extern PyTypeObject PyBlake2_BLAKE2bType; -extern PyTypeObject PyBlake2_BLAKE2sType; - +extern PyType_Spec blake2b_type_spec; +extern PyType_Spec blake2s_type_spec; PyDoc_STRVAR(blake2mod__doc__, "_blake2b provides BLAKE2b for hashlib\n" ); +typedef struct { + PyTypeObject* blake2b_type; + PyTypeObject* blake2s_type; +} Blake2State; + +static inline Blake2State* +blake2_get_state(PyObject *module) +{ + void *state = PyModule_GetState(module); + assert(state != NULL); + return (Blake2State *)state; +} static struct PyMethodDef blake2mod_functions[] = { {NULL, NULL} }; -static struct PyModuleDef blake2_module = { - PyModuleDef_HEAD_INIT, - "_blake2", - blake2mod__doc__, - -1, - blake2mod_functions, - NULL, - NULL, - NULL, - NULL -}; +static int +_blake2_traverse(PyObject *module, visitproc visit, void *arg) +{ + Blake2State *state = blake2_get_state(module); + Py_VISIT(state->blake2b_type); + Py_VISIT(state->blake2s_type); + return 0; +} + +static int +_blake2_clear(PyObject *module) +{ + Blake2State *state = blake2_get_state(module); + Py_CLEAR(state->blake2b_type); + Py_CLEAR(state->blake2s_type); + return 0; +} + +static void +_blake2_free(void *module) +{ + _blake2_clear((PyObject *)module); +} #define ADD_INT(d, name, value) do { \ PyObject *x = PyLong_FromLong(value); \ - if (!x) { \ - Py_DECREF(m); \ - return NULL; \ - } \ + if (!x) \ + return -1; \ if (PyDict_SetItemString(d, name, x) < 0) { \ - Py_DECREF(m); \ - return NULL; \ + Py_DECREF(x); \ + return -1; \ } \ Py_DECREF(x); \ } while(0) - -PyMODINIT_FUNC -PyInit__blake2(void) +static int +blake2_exec(PyObject *m) { - PyObject *m; - PyObject *d; + Blake2State* st = blake2_get_state(m); - m = PyModule_Create(&blake2_module); - if (m == NULL) - return NULL; + st->blake2b_type = (PyTypeObject *)PyType_FromModuleAndSpec( + m, &blake2b_type_spec, NULL); + if (NULL == st->blake2b_type) + return -1; /* BLAKE2b */ - Py_SET_TYPE(&PyBlake2_BLAKE2bType, &PyType_Type); - if (PyModule_AddType(m, &PyBlake2_BLAKE2bType) < 0) { - return NULL; + if (PyModule_AddType(m, st->blake2b_type) < 0) { + return -1; } - d = PyBlake2_BLAKE2bType.tp_dict; + PyObject *d = st->blake2b_type->tp_dict; ADD_INT(d, "SALT_SIZE", BLAKE2B_SALTBYTES); ADD_INT(d, "PERSON_SIZE", BLAKE2B_PERSONALBYTES); ADD_INT(d, "MAX_KEY_SIZE", BLAKE2B_KEYBYTES); @@ -79,12 +98,17 @@ PyInit__blake2(void) PyModule_AddIntConstant(m, "BLAKE2B_MAX_DIGEST_SIZE", BLAKE2B_OUTBYTES); /* BLAKE2s */ - Py_SET_TYPE(&PyBlake2_BLAKE2sType, &PyType_Type); - if (PyModule_AddType(m, &PyBlake2_BLAKE2sType) < 0) { - return NULL; + st->blake2s_type = (PyTypeObject *)PyType_FromModuleAndSpec( + m, &blake2s_type_spec, NULL); + + if (NULL == st->blake2s_type) + return -1; + + if (PyModule_AddType(m, st->blake2s_type) < 0) { + return -1; } - d = PyBlake2_BLAKE2sType.tp_dict; + d = st->blake2s_type->tp_dict; ADD_INT(d, "SALT_SIZE", BLAKE2S_SALTBYTES); ADD_INT(d, "PERSON_SIZE", BLAKE2S_PERSONALBYTES); ADD_INT(d, "MAX_KEY_SIZE", BLAKE2S_KEYBYTES); @@ -95,5 +119,28 @@ PyInit__blake2(void) PyModule_AddIntConstant(m, "BLAKE2S_MAX_KEY_SIZE", BLAKE2S_KEYBYTES); PyModule_AddIntConstant(m, "BLAKE2S_MAX_DIGEST_SIZE", BLAKE2S_OUTBYTES); - return m; + return 0; } + +static PyModuleDef_Slot _blake2_slots[] = { + {Py_mod_exec, blake2_exec}, + {0, NULL} +}; + +static struct PyModuleDef blake2_module = { + PyModuleDef_HEAD_INIT, + "_blake2", + .m_doc = blake2mod__doc__, + .m_size = sizeof(Blake2State), + .m_methods = blake2mod_functions, + .m_slots = _blake2_slots, + .m_traverse = _blake2_traverse, + .m_clear = _blake2_clear, + .m_free = _blake2_free, +}; + +PyMODINIT_FUNC +PyInit__blake2(void) +{ + return PyModuleDef_Init(&blake2_module); +} \ No newline at end of file diff --git a/Modules/_blake2/blake2s_impl.c b/Modules/_blake2/blake2s_impl.c index e3e90d0587b805..e1de5df37d0988 100644 --- a/Modules/_blake2/blake2s_impl.c +++ b/Modules/_blake2/blake2s_impl.c @@ -33,8 +33,7 @@ #include "impl/blake2s-ref.c" #endif - -extern PyTypeObject PyBlake2_BLAKE2sType; +extern PyType_Spec blake2s_type_spec; typedef struct { PyObject_HEAD @@ -391,47 +390,24 @@ py_blake2s_dealloc(PyObject *self) PyThread_free_lock(obj->lock); obj->lock = NULL; } + + PyTypeObject *type = Py_TYPE(self); PyObject_Del(self); + Py_DECREF(type); } +static PyType_Slot blake2s_type_slots[] = { + {Py_tp_dealloc, py_blake2s_dealloc}, + {Py_tp_doc, (char *)py_blake2s_new__doc__}, + {Py_tp_methods, py_blake2s_methods}, + {Py_tp_getset, py_blake2s_getsetters}, + {Py_tp_new, py_blake2s_new}, + {0,0} +}; -PyTypeObject PyBlake2_BLAKE2sType = { - PyVarObject_HEAD_INIT(NULL, 0) - "_blake2.blake2s", /* tp_name */ - sizeof(BLAKE2sObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - py_blake2s_dealloc, /* tp_dealloc */ - 0, /*tp_vectorcall_offset*/ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ - py_blake2s_new__doc__, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - py_blake2s_methods, /* tp_methods */ - 0, /* tp_members */ - py_blake2s_getsetters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - py_blake2s_new, /* tp_new */ +PyType_Spec blake2s_type_spec = { + .name = "_blake2.blake2s", + .basicsize = sizeof(BLAKE2sObject), + .flags = Py_TPFLAGS_DEFAULT, + .slots = blake2s_type_slots }; From 93d50a6a8d0c5d332c11aef267e66573a09765ac Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Wed, 2 Sep 2020 04:55:19 -0500 Subject: [PATCH 42/63] bpo-1635741: Port _sha3 module to multi-phase init (GH-21855) Port the _sha3 extension module to multi-phase init (PEP 489). Convert static types to heap types. --- ...2020-08-13-07-19-21.bpo-1653741.fubBkb.rst | 1 + Modules/_sha3/sha3module.c | 329 ++++++++++-------- 2 files changed, 194 insertions(+), 136 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2020-08-13-07-19-21.bpo-1653741.fubBkb.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-08-13-07-19-21.bpo-1653741.fubBkb.rst b/Misc/NEWS.d/next/Core and Builtins/2020-08-13-07-19-21.bpo-1653741.fubBkb.rst new file mode 100644 index 00000000000000..73a4fdbac48a24 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-08-13-07-19-21.bpo-1653741.fubBkb.rst @@ -0,0 +1 @@ +Port :mod:`_sha3` to multi-phase init. Convert static types to heap types. diff --git a/Modules/_sha3/sha3module.c b/Modules/_sha3/sha3module.c index c826b42df13f92..da6dde6812f264 100644 --- a/Modules/_sha3/sha3module.c +++ b/Modules/_sha3/sha3module.c @@ -122,6 +122,28 @@ #define SHA3_squeeze Keccak_HashSqueeze #define SHA3_copystate(dest, src) memcpy(&(dest), &(src), sizeof(SHA3_state)) +typedef struct { + PyTypeObject *sha3_224_type; + PyTypeObject *sha3_256_type; + PyTypeObject *sha3_384_type; + PyTypeObject *sha3_512_type; +#ifdef PY_WITH_KECCAK + PyTypeObject *keccak_224_type; + PyTypeObject *keccak_256_type; + PyTypeObject *keccak_384_type; + PyTypeObject *keccak_512_type; +#endif + PyTypeObject *shake_128_type; + PyTypeObject *shake_256_type; +} SHA3State; + +static inline SHA3State* +sha3_get_state(PyObject *module) +{ + void *state = PyModule_GetState(module); + assert(state != NULL); + return (SHA3State *)state; +} /*[clinic input] module _sha3 @@ -142,19 +164,6 @@ typedef struct { PyThread_type_lock lock; } SHA3object; -static PyTypeObject SHA3_224type; -static PyTypeObject SHA3_256type; -static PyTypeObject SHA3_384type; -static PyTypeObject SHA3_512type; -#ifdef PY_WITH_KECCAK -static PyTypeObject Keccak_224type; -static PyTypeObject Keccak_256type; -static PyTypeObject Keccak_384type; -static PyTypeObject Keccak_512type; -#endif -static PyTypeObject SHAKE128type; -static PyTypeObject SHAKE256type; - #include "clinic/sha3module.c.h" static SHA3object * @@ -184,42 +193,43 @@ static PyObject * py_sha3_new_impl(PyTypeObject *type, PyObject *data, int usedforsecurity) /*[clinic end generated code: output=90409addc5d5e8b0 input=bcfcdf2e4368347a]*/ { - SHA3object *self = NULL; - Py_buffer buf = {NULL, NULL}; - HashReturn res; - - self = newSHA3object(type); + SHA3object *self = newSHA3object(type); if (self == NULL) { goto error; } - if (type == &SHA3_224type) { + SHA3State *state = PyType_GetModuleState(type); + assert(state != NULL); + + HashReturn res; + if (type == state->sha3_224_type) { res = Keccak_HashInitialize_SHA3_224(&self->hash_state); - } else if (type == &SHA3_256type) { + } else if (type == state->sha3_256_type) { res = Keccak_HashInitialize_SHA3_256(&self->hash_state); - } else if (type == &SHA3_384type) { + } else if (type == state->sha3_384_type) { res = Keccak_HashInitialize_SHA3_384(&self->hash_state); - } else if (type == &SHA3_512type) { + } else if (type == state->sha3_512_type) { res = Keccak_HashInitialize_SHA3_512(&self->hash_state); #ifdef PY_WITH_KECCAK - } else if (type == &Keccak_224type) { + } else if (type == state->keccak_224_type) { res = Keccak_HashInitialize(&self->hash_state, 1152, 448, 224, 0x01); - } else if (type == &Keccak_256type) { + } else if (type == state->keccak_256_type) { res = Keccak_HashInitialize(&self->hash_state, 1088, 512, 256, 0x01); - } else if (type == &Keccak_384type) { + } else if (type == state->keccak_384_type) { res = Keccak_HashInitialize(&self->hash_state, 832, 768, 384, 0x01); - } else if (type == &Keccak_512type) { + } else if (type == state->keccak_512_type) { res = Keccak_HashInitialize(&self->hash_state, 576, 1024, 512, 0x01); #endif - } else if (type == &SHAKE128type) { + } else if (type == state->shake_128_type) { res = Keccak_HashInitialize_SHAKE128(&self->hash_state); - } else if (type == &SHAKE256type) { + } else if (type == state->shake_256_type) { res = Keccak_HashInitialize_SHAKE256(&self->hash_state); } else { PyErr_BadInternalCall(); goto error; } + Py_buffer buf = {NULL, NULL}; if (data) { GET_BUFFER_VIEW_OR_ERROR(data, &buf, goto error); if (buf.len >= HASHLIB_GIL_MINSIZE) { @@ -262,7 +272,10 @@ SHA3_dealloc(SHA3object *self) if (self->lock) { PyThread_free_lock(self->lock); } + + PyTypeObject *tp = Py_TYPE(self); PyObject_Del(self); + Py_DECREF(tp); } @@ -416,27 +429,31 @@ static PyObject * SHA3_get_name(SHA3object *self, void *closure) { PyTypeObject *type = Py_TYPE(self); - if (type == &SHA3_224type) { + + SHA3State *state = PyType_GetModuleState(type); + assert(state != NULL); + + if (type == state->sha3_224_type) { return PyUnicode_FromString("sha3_224"); - } else if (type == &SHA3_256type) { + } else if (type == state->sha3_256_type) { return PyUnicode_FromString("sha3_256"); - } else if (type == &SHA3_384type) { + } else if (type == state->sha3_384_type) { return PyUnicode_FromString("sha3_384"); - } else if (type == &SHA3_512type) { + } else if (type == state->sha3_512_type) { return PyUnicode_FromString("sha3_512"); #ifdef PY_WITH_KECCAK - } else if (type == &Keccak_224type) { + } else if (type == state->keccak_224_type) { return PyUnicode_FromString("keccak_224"); - } else if (type == &Keccak_256type) { + } else if (type == state->keccak_256_type) { return PyUnicode_FromString("keccak_256"); - } else if (type == &Keccak_384type) { + } else if (type == state->keccak_384_type) { return PyUnicode_FromString("keccak_384"); - } else if (type == &Keccak_512type) { + } else if (type == state->keccak_512_type) { return PyUnicode_FromString("keccak_512"); #endif - } else if (type == &SHAKE128type) { + } else if (type == state->shake_128_type) { return PyUnicode_FromString("shake_128"); - } else if (type == &SHAKE256type) { + } else if (type == state->shake_256_type) { return PyUnicode_FromString("shake_256"); } else { PyErr_BadInternalCall(); @@ -476,7 +493,6 @@ SHA3_get_suffix(SHA3object *self, void *closure) return PyBytes_FromStringAndSize((const char *)suffix, 1); } - static PyGetSetDef SHA3_getseters[] = { {"block_size", (getter)SHA3_get_block_size, NULL, NULL, NULL}, {"name", (getter)SHA3_get_name, NULL, NULL, NULL}, @@ -487,48 +503,24 @@ static PyGetSetDef SHA3_getseters[] = { {NULL} /* Sentinel */ }; +#define SHA3_TYPE_SLOTS(type_slots_obj, type_doc, type_methods) \ + static PyType_Slot type_slots_obj[] = { \ + {Py_tp_dealloc, SHA3_dealloc}, \ + {Py_tp_doc, (char*)type_doc}, \ + {Py_tp_methods, type_methods}, \ + {Py_tp_getset, SHA3_getseters}, \ + {Py_tp_new, py_sha3_new}, \ + {0,0} \ + } -#define SHA3_TYPE(type_obj, type_name, type_doc, type_methods) \ - static PyTypeObject type_obj = { \ - PyVarObject_HEAD_INIT(NULL, 0) \ - type_name, /* tp_name */ \ - sizeof(SHA3object), /* tp_basicsize */ \ - 0, /* tp_itemsize */ \ - /* methods */ \ - (destructor)SHA3_dealloc, /* tp_dealloc */ \ - 0, /* tp_vectorcall_offset */ \ - 0, /* tp_getattr */ \ - 0, /* tp_setattr */ \ - 0, /* tp_as_async */ \ - 0, /* tp_repr */ \ - 0, /* tp_as_number */ \ - 0, /* tp_as_sequence */ \ - 0, /* tp_as_mapping */ \ - 0, /* tp_hash */ \ - 0, /* tp_call */ \ - 0, /* tp_str */ \ - 0, /* tp_getattro */ \ - 0, /* tp_setattro */ \ - 0, /* tp_as_buffer */ \ - Py_TPFLAGS_DEFAULT, /* tp_flags */ \ - type_doc, /* tp_doc */ \ - 0, /* tp_traverse */ \ - 0, /* tp_clear */ \ - 0, /* tp_richcompare */ \ - 0, /* tp_weaklistoffset */ \ - 0, /* tp_iter */ \ - 0, /* tp_iternext */ \ - type_methods, /* tp_methods */ \ - NULL, /* tp_members */ \ - SHA3_getseters, /* tp_getset */ \ - 0, /* tp_base */ \ - 0, /* tp_dict */ \ - 0, /* tp_descr_get */ \ - 0, /* tp_descr_set */ \ - 0, /* tp_dictoffset */ \ - 0, /* tp_init */ \ - 0, /* tp_alloc */ \ - py_sha3_new, /* tp_new */ \ +// Using PyType_GetModuleState() on these types is safe since they +// cannot be subclassed: it does not have the Py_TPFLAGS_BASETYPE flag. +#define SHA3_TYPE_SPEC(type_spec_obj, type_name, type_slots) \ + static PyType_Spec type_spec_obj = { \ + .name = "_sha3." type_name, \ + .basicsize = sizeof(SHA3object), \ + .flags = Py_TPFLAGS_DEFAULT, \ + .slots = type_slots \ } PyDoc_STRVAR(sha3_224__doc__, @@ -551,11 +543,6 @@ PyDoc_STRVAR(sha3_512__doc__, \n\ Return a new SHA3 hash object with a hashbit length of 64 bytes."); -SHA3_TYPE(SHA3_224type, "_sha3.sha3_224", sha3_224__doc__, SHA3_methods); -SHA3_TYPE(SHA3_256type, "_sha3.sha3_256", sha3_256__doc__, SHA3_methods); -SHA3_TYPE(SHA3_384type, "_sha3.sha3_384", sha3_384__doc__, SHA3_methods); -SHA3_TYPE(SHA3_512type, "_sha3.sha3_512", sha3_512__doc__, SHA3_methods); - #ifdef PY_WITH_KECCAK PyDoc_STRVAR(keccak_224__doc__, "keccak_224([data], *, usedforsecurity=True) -> Keccak object\n\ @@ -577,10 +564,32 @@ PyDoc_STRVAR(keccak_512__doc__, \n\ Return a new Keccak hash object with a hashbit length of 64 bytes."); -SHA3_TYPE(Keccak_224type, "_sha3.keccak_224", keccak_224__doc__, SHA3_methods); -SHA3_TYPE(Keccak_256type, "_sha3.keccak_256", keccak_256__doc__, SHA3_methods); -SHA3_TYPE(Keccak_384type, "_sha3.keccak_384", keccak_384__doc__, SHA3_methods); -SHA3_TYPE(Keccak_512type, "_sha3.keccak_512", keccak_512__doc__, SHA3_methods); +#endif + +SHA3_TYPE_SLOTS(sha3_224_slots, sha3_224__doc__, SHA3_methods); +SHA3_TYPE_SPEC(sha3_224_spec, "sha3_224", sha3_224_slots); + +SHA3_TYPE_SLOTS(sha3_256_slots, sha3_256__doc__, SHA3_methods); +SHA3_TYPE_SPEC(sha3_256_spec, "sha3_256", sha3_256_slots); + +SHA3_TYPE_SLOTS(sha3_384_slots, sha3_384__doc__, SHA3_methods); +SHA3_TYPE_SPEC(sha3_384_spec, "sha3_384", sha3_384_slots); + +SHA3_TYPE_SLOTS(sha3_512_slots, sha3_512__doc__, SHA3_methods); +SHA3_TYPE_SPEC(sha3_512_spec, "sha3_512", sha3_512_slots); + +#ifdef PY_WITH_KECCAK +SHA3_TYPE_SLOTS(Keccak_224_slots, keccak_224__doc__, SHA3_methods); +SHA3_TYPE_SPEC(Keccak_224_spec, "keccak_224", Keccak_224_slots); + +SHA3_TYPE_SLOTS(Keccak_256_slots, keccak_256__doc__, SHA3_methods); +SHA3_TYPE_SPEC(Keccak_256_spec, "keccak_256", Keccak_256_slots); + +SHA3_TYPE_SLOTS(Keccak_384_slots, keccak_384__doc__, SHA3_methods); +SHA3_TYPE_SPEC(Keccak_384_spec, "keccak_384", Keccak_384_slots); + +SHA3_TYPE_SLOTS(Keccak_512_slots, keccak_512__doc__, SHA3_methods); +SHA3_TYPE_SPEC(Keccak_512_spec, "keccak_512", Keccak_512_slots); #endif @@ -684,70 +693,118 @@ PyDoc_STRVAR(shake_256__doc__, \n\ Return a new SHAKE hash object."); -SHA3_TYPE(SHAKE128type, "_sha3.shake_128", shake_128__doc__, SHAKE_methods); -SHA3_TYPE(SHAKE256type, "_sha3.shake_256", shake_256__doc__, SHAKE_methods); +SHA3_TYPE_SLOTS(SHAKE128slots, shake_128__doc__, SHAKE_methods); +SHA3_TYPE_SPEC(SHAKE128_spec, "shake_128", SHAKE128slots); +SHA3_TYPE_SLOTS(SHAKE256slots, shake_256__doc__, SHAKE_methods); +SHA3_TYPE_SPEC(SHAKE256_spec, "shake_256", SHAKE256slots); -/* Initialize this module. */ -static struct PyModuleDef _SHA3module = { - PyModuleDef_HEAD_INIT, - "_sha3", - NULL, - -1, - NULL, - NULL, - NULL, - NULL, - NULL -}; +static int +_sha3_traverse(PyObject *module, visitproc visit, void *arg) +{ + SHA3State *state = sha3_get_state(module); + Py_VISIT(state->sha3_224_type); + Py_VISIT(state->sha3_256_type); + Py_VISIT(state->sha3_384_type); + Py_VISIT(state->sha3_512_type); +#ifdef PY_WITH_KECCAK + Py_VISIT(state->keccak_224_type); + Py_VISIT(state->keccak_256_type); + Py_VISIT(state->keccak_384_type); + Py_VISIT(state->keccak_512_type); +#endif + Py_VISIT(state->shake_128_type); + Py_VISIT(state->shake_256_type); + return 0; +} -PyMODINIT_FUNC -PyInit__sha3(void) +static int +_sha3_clear(PyObject *module) { - PyObject *m = NULL; + SHA3State *state = sha3_get_state(module); + Py_CLEAR(state->sha3_224_type); + Py_CLEAR(state->sha3_256_type); + Py_CLEAR(state->sha3_384_type); + Py_CLEAR(state->sha3_512_type); +#ifdef PY_WITH_KECCAK + Py_CLEAR(state->keccak_224_type); + Py_CLEAR(state->keccak_256_type); + Py_CLEAR(state->keccak_384_type); + Py_CLEAR(state->keccak_512_type); +#endif + Py_CLEAR(state->shake_128_type); + Py_CLEAR(state->shake_256_type); + return 0; +} - if ((m = PyModule_Create(&_SHA3module)) == NULL) { - return NULL; - } +static void +_sha3_free(void *module) +{ + _sha3_clear((PyObject *)module); +} -#define init_sha3type(name, type) \ - do { \ - Py_SET_TYPE(type, &PyType_Type); \ - if (PyType_Ready(type) < 0) { \ - goto error; \ - } \ - Py_INCREF((PyObject *)type); \ - if (PyModule_AddObject(m, name, (PyObject *)type) < 0) { \ - goto error; \ - } \ +static int +_sha3_exec(PyObject *m) +{ + SHA3State *st = sha3_get_state(m); + +#define init_sha3type(type, typespec) \ + do { \ + st->type = (PyTypeObject *)PyType_FromModuleAndSpec( \ + m, &typespec, NULL); \ + if (st->type == NULL) { \ + return -1; \ + } \ + if (PyModule_AddType(m, st->type) < 0) { \ + return -1; \ + } \ } while(0) - init_sha3type("sha3_224", &SHA3_224type); - init_sha3type("sha3_256", &SHA3_256type); - init_sha3type("sha3_384", &SHA3_384type); - init_sha3type("sha3_512", &SHA3_512type); + init_sha3type(sha3_224_type, sha3_224_spec); + init_sha3type(sha3_256_type, sha3_256_spec); + init_sha3type(sha3_384_type, sha3_384_spec); + init_sha3type(sha3_512_type, sha3_512_spec); #ifdef PY_WITH_KECCAK - init_sha3type("keccak_224", &Keccak_224type); - init_sha3type("keccak_256", &Keccak_256type); - init_sha3type("keccak_384", &Keccak_384type); - init_sha3type("keccak_512", &Keccak_512type); + init_sha3type(keccak_224_type, Keccak_224_spec); + init_sha3type(keccak_256_type, Keccak_256_spec); + init_sha3type(keccak_384_type, Keccak_384_spec); + init_sha3type(keccak_512_type, Keccak_512_spec); #endif - init_sha3type("shake_128", &SHAKE128type); - init_sha3type("shake_256", &SHAKE256type); - + init_sha3type(shake_128_type, SHAKE128_spec); + init_sha3type(shake_256_type, SHAKE256_spec); #undef init_sha3type if (PyModule_AddIntConstant(m, "keccakopt", KeccakOpt) < 0) { - goto error; + return -1; } if (PyModule_AddStringConstant(m, "implementation", KeccakP1600_implementation) < 0) { - goto error; + return -1; } - return m; - error: - Py_DECREF(m); - return NULL; + return 0; +} + +static PyModuleDef_Slot _sha3_slots[] = { + {Py_mod_exec, _sha3_exec}, + {0, NULL} +}; + +/* Initialize this module. */ +static struct PyModuleDef _sha3module = { + PyModuleDef_HEAD_INIT, + .m_name = "_sha3", + .m_size = sizeof(SHA3State), + .m_slots = _sha3_slots, + .m_traverse = _sha3_traverse, + .m_clear = _sha3_clear, + .m_free = _sha3_free, +}; + + +PyMODINIT_FUNC +PyInit__sha3(void) +{ + return PyModuleDef_Init(&_sha3module); } From c0d5c131d9c1ac743058fae99f913b455fc90ac7 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 2 Sep 2020 12:29:31 +0200 Subject: [PATCH 43/63] bpo-40204: Update Sphinx to version 3.2.1 in Doc/Makefile (GH-22043) --- Doc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/Makefile b/Doc/Makefile index 87d5d07665c863..f1d0a267dd89d5 100644 --- a/Doc/Makefile +++ b/Doc/Makefile @@ -144,7 +144,7 @@ venv: $(PYTHON) -m venv $(VENVDIR) # $(VENVDIR)/bin/python3 -m pip install -U pip setuptools $(VENVDIR)/bin/python3 -m pip install -U pip setuptools==49.2.1 - $(VENVDIR)/bin/python3 -m pip install -U Sphinx==2.3.1 blurb python-docs-theme + $(VENVDIR)/bin/python3 -m pip install -U Sphinx==3.2.1 blurb python-docs-theme @echo "The venv has been created in the $(VENVDIR) directory" dist: From 51fece1bb8d7aa22f114172a256714fe24788e31 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 2 Sep 2020 13:11:21 +0200 Subject: [PATCH 44/63] bpo-41685: Don't pin setuptools version anymore in Doc/Makefile (GH-22062) setuptools 50.0.2 is now compatible with Python 3.10: https://github.com/pypa/setuptools/pull/2361 --- Doc/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Doc/Makefile b/Doc/Makefile index f1d0a267dd89d5..c11a7ca5c1bcb7 100644 --- a/Doc/Makefile +++ b/Doc/Makefile @@ -142,8 +142,7 @@ clean: venv: $(PYTHON) -m venv $(VENVDIR) -# $(VENVDIR)/bin/python3 -m pip install -U pip setuptools - $(VENVDIR)/bin/python3 -m pip install -U pip setuptools==49.2.1 + $(VENVDIR)/bin/python3 -m pip install -U pip setuptools $(VENVDIR)/bin/python3 -m pip install -U Sphinx==3.2.1 blurb python-docs-theme @echo "The venv has been created in the $(VENVDIR) directory" From f9c5e3f5f61cd380f8a17c814766fc3730b7fbdf Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Wed, 2 Sep 2020 15:29:12 +0100 Subject: [PATCH 45/63] bpo-41675: Modernize siginterrupt calls (GH-22028) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit siginterrupt is deprecated: ./Modules/signalmodule.c:667:5: warning: ‘siginterrupt’ is deprecated: Use sigaction with SA_RESTART instead [-Wdeprecated-declarations] 667 | if (siginterrupt(signalnum, flag)<0) { --- .../2020-08-31-14-53-17.bpo-41675.VSoqWU.rst | 3 +++ Modules/signalmodule.c | 14 +++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2020-08-31-14-53-17.bpo-41675.VSoqWU.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-08-31-14-53-17.bpo-41675.VSoqWU.rst b/Misc/NEWS.d/next/Core and Builtins/2020-08-31-14-53-17.bpo-41675.VSoqWU.rst new file mode 100644 index 00000000000000..aa102f8fe43845 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-08-31-14-53-17.bpo-41675.VSoqWU.rst @@ -0,0 +1,3 @@ +The implementation of :func:`signal.siginterrupt` now uses :c:func:`sigaction` +(if it is available in the system) instead of the deprecated :c:func:`siginterrupt`. +Patch by Pablo Galindo. diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index 7bc1b535e6e2ca..c49a3ea52e71de 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -664,7 +664,19 @@ signal_siginterrupt_impl(PyObject *module, int signalnum, int flag) "signal number out of range"); return NULL; } - if (siginterrupt(signalnum, flag)<0) { +#ifdef HAVE_SIGACTION + struct sigaction act; + (void) sigaction(signalnum, NULL, &act); + if (flag) { + act.sa_flags &= ~SA_RESTART; + } + else { + act.sa_flags |= SA_RESTART; + } + if (sigaction(signalnum, &act, NULL) < 0) { +#else + if (siginterrupt(signalnum, flag) < 0) { +#endif PyErr_SetFromErrno(PyExc_OSError); return NULL; } From 5a4a963a6c798fa9207a9998618a9c0ec3b6b6d7 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Wed, 2 Sep 2020 15:29:38 +0100 Subject: [PATCH 46/63] Fix invalid escape sequences in the peg_highlight Sphinx extension (GH-22047) --- Doc/tools/extensions/peg_highlight.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/tools/extensions/peg_highlight.py b/Doc/tools/extensions/peg_highlight.py index f02515d3919cf2..8bc24670fbe0ab 100644 --- a/Doc/tools/extensions/peg_highlight.py +++ b/Doc/tools/extensions/peg_highlight.py @@ -59,7 +59,7 @@ class PEGLexer(RegexLexer): include("variables"), (r"\b(?!(NULL|EXTRA))([A-Z_]+)\b\s*(?!\()", Text,), ( - r"^\s*" + _name + "\s*" + "(\[.*\])?" + "\s*" + "(\(.+\))?" + "\s*(:)", + r"^\s*" + _name + r"\s*" + r"(\[.*\])?" + r"\s*" + r"(\(.+\))?" + r"\s*(:)", bygroups(Name.Function, None, None, Punctuation), ), (_name, Name.Function), From 3940333637b98a2781869977b077552514784529 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 2 Sep 2020 11:29:06 -0500 Subject: [PATCH 47/63] closes bpo-41689: Preserve text signature from tp_doc in C heap type creation. (GH-22058) --- Lib/test/test_capi.py | 4 +++ .../2020-09-01-23-39-45.bpo-41689.zxHbLB.rst | 2 ++ Modules/_testcapimodule.c | 30 +++++++++++++++++++ Objects/typeobject.c | 15 ++++++++-- 4 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2020-09-01-23-39-45.bpo-41689.zxHbLB.rst diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py index 892cc74ec39158..db62b47100ad3a 100644 --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -401,6 +401,10 @@ def __del__(self): del L self.assertEqual(PyList.num, 0) + def test_heap_ctype_doc_and_text_signature(self): + self.assertEqual(_testcapi.HeapDocCType.__doc__, "somedoc") + self.assertEqual(_testcapi.HeapDocCType.__text_signature__, "(arg1, arg2)") + def test_subclass_of_heap_gc_ctype_with_tpdealloc_decrefs_once(self): class HeapGcCTypeSubclass(_testcapi.HeapGcCType): def __init__(self): diff --git a/Misc/NEWS.d/next/C API/2020-09-01-23-39-45.bpo-41689.zxHbLB.rst b/Misc/NEWS.d/next/C API/2020-09-01-23-39-45.bpo-41689.zxHbLB.rst new file mode 100644 index 00000000000000..44cf58a4b06388 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2020-09-01-23-39-45.bpo-41689.zxHbLB.rst @@ -0,0 +1,2 @@ +Types created with :c:func:`PyType_FromSpec` now make any signature in their +``tp_doc`` slot accessible from ``__text_signature__``. diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 593034ef65e2ca..7536d29535038c 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -6462,6 +6462,30 @@ static PyTypeObject MethodDescriptor2_Type = { .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_VECTORCALL, }; +PyDoc_STRVAR(heapdocctype__doc__, +"HeapDocCType(arg1, arg2)\n" +"--\n" +"\n" +"somedoc"); + +typedef struct { + PyObject_HEAD +} HeapDocCTypeObject; + +static PyType_Slot HeapDocCType_slots[] = { + {Py_tp_doc, (char*)heapdocctype__doc__}, + {0}, +}; + +static PyType_Spec HeapDocCType_spec = { + "_testcapi.HeapDocCType", + sizeof(HeapDocCTypeObject), + 0, + Py_TPFLAGS_DEFAULT, + HeapDocCType_slots +}; + + PyDoc_STRVAR(heapgctype__doc__, "A heap type with GC, and with overridden dealloc.\n\n" "The 'value' attribute is set to 10 in __init__."); @@ -7130,6 +7154,12 @@ PyInit__testcapi(void) Py_INCREF(TestError); PyModule_AddObject(m, "error", TestError); + PyObject *HeapDocCType = PyType_FromSpec(&HeapDocCType_spec); + if (HeapDocCType == NULL) { + return NULL; + } + PyModule_AddObject(m, "HeapDocCType", HeapDocCType); + PyObject *HeapGcCType = PyType_FromSpec(&HeapGcCType_spec); if (HeapGcCType == NULL) { return NULL; diff --git a/Objects/typeobject.c b/Objects/typeobject.c index c66f8fcec8ed51..74040757a07021 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3018,15 +3018,14 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases) else if (slot->slot == Py_tp_doc) { /* For the docstring slot, which usually points to a static string literal, we need to make a copy */ - const char *old_doc = _PyType_DocWithoutSignature(type->tp_name, slot->pfunc); - size_t len = strlen(old_doc)+1; + size_t len = strlen(slot->pfunc)+1; char *tp_doc = PyObject_MALLOC(len); if (tp_doc == NULL) { type->tp_doc = NULL; PyErr_NoMemory(); goto fail; } - memcpy(tp_doc, old_doc, len); + memcpy(tp_doc, slot->pfunc, len); type->tp_doc = tp_doc; } else if (slot->slot == Py_tp_members) { @@ -3058,6 +3057,16 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases) res->ht_cached_keys = _PyDict_NewKeysForClass(); } + if (type->tp_doc) { + PyObject *__doc__ = PyUnicode_FromString(_PyType_DocWithoutSignature(type->tp_name, type->tp_doc)); + if (!__doc__) + goto fail; + int ret = _PyDict_SetItemId(type->tp_dict, &PyId___doc__, __doc__); + Py_DECREF(__doc__); + if (ret < 0) + goto fail; + } + if (weaklistoffset) { type->tp_weaklistoffset = weaklistoffset; if (PyDict_DelItemString((PyObject *)type->tp_dict, "__weaklistoffset__") < 0) From 4a97b1517a6b5ff22e2984b677a680b07ff0ce11 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Wed, 2 Sep 2020 17:44:19 +0100 Subject: [PATCH 48/63] bpo-41690: Use a loop to collect args in the parser instead of recursion (GH-22053) This program can segfault the parser by stack overflow: ``` import ast code = "f(" + ",".join(['a' for _ in range(100000)]) + ")" print("Ready!") ast.parse(code) ``` the reason is that the rule for arguments has a simple recursion when collecting args: args[expr_ty]: [...] | a=named_expression b=[',' c=args { c }] { [...] } --- Grammar/python.gram | 13 +- .../2020-09-02-12-00-57.bpo-41690.Ny-Sfy.rst | 2 + Parser/parser.c | 1092 +++++++++-------- Parser/pegen.c | 35 + Parser/pegen.h | 1 + 5 files changed, 628 insertions(+), 515 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2020-09-02-12-00-57.bpo-41690.Ny-Sfy.rst diff --git a/Grammar/python.gram b/Grammar/python.gram index 1cba11407468d2..84835b731c540f 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -535,22 +535,11 @@ arguments[expr_ty] (memo): | a=args [','] &')' { a } | incorrect_arguments args[expr_ty]: - | a=starred_expression b=[',' c=args { c }] { - _Py_Call(_PyPegen_dummy_name(p), - (b) ? CHECK(_PyPegen_seq_insert_in_front(p, a, ((expr_ty) b)->v.Call.args)) - : CHECK(_PyPegen_singleton_seq(p, a)), - (b) ? ((expr_ty) b)->v.Call.keywords : NULL, - EXTRA) } + | a=','.(starred_expression | named_expression !'=')+ b=[',' k=kwargs {k}] { _PyPegen_collect_call_seqs(p, a, b) } | a=kwargs { _Py_Call(_PyPegen_dummy_name(p), CHECK_NULL_ALLOWED(_PyPegen_seq_extract_starred_exprs(p, a)), CHECK_NULL_ALLOWED(_PyPegen_seq_delete_starred_exprs(p, a)), EXTRA) } - | a=named_expression b=[',' c=args { c }] { - _Py_Call(_PyPegen_dummy_name(p), - (b) ? CHECK(_PyPegen_seq_insert_in_front(p, a, ((expr_ty) b)->v.Call.args)) - : CHECK(_PyPegen_singleton_seq(p, a)), - (b) ? ((expr_ty) b)->v.Call.keywords : NULL, - EXTRA) } kwargs[asdl_seq*]: | a=','.kwarg_or_starred+ ',' b=','.kwarg_or_double_starred+ { _PyPegen_join_sequences(p, a, b) } | ','.kwarg_or_starred+ diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-09-02-12-00-57.bpo-41690.Ny-Sfy.rst b/Misc/NEWS.d/next/Core and Builtins/2020-09-02-12-00-57.bpo-41690.Ny-Sfy.rst new file mode 100644 index 00000000000000..5711aa5a55f070 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-09-02-12-00-57.bpo-41690.Ny-Sfy.rst @@ -0,0 +1,2 @@ +Fix a possible stack overflow in the parser when parsing functions and +classes with a huge ammount of arguments. Patch by Pablo Galindo. diff --git a/Parser/parser.c b/Parser/parser.c index 75dc7176a5e756..3e724a260d90a9 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -334,34 +334,34 @@ static KeywordToken *reserved_keywords[] = { #define _loop1_105_type 1265 #define _loop0_106_type 1266 #define _loop0_107_type 1267 -#define _tmp_108_type 1268 -#define _tmp_109_type 1269 -#define _loop0_111_type 1270 -#define _gather_110_type 1271 -#define _loop0_113_type 1272 -#define _gather_112_type 1273 -#define _loop0_115_type 1274 -#define _gather_114_type 1275 -#define _loop0_117_type 1276 -#define _gather_116_type 1277 -#define _loop0_118_type 1278 -#define _loop0_120_type 1279 -#define _gather_119_type 1280 -#define _tmp_121_type 1281 -#define _loop0_123_type 1282 -#define _gather_122_type 1283 -#define _loop0_125_type 1284 -#define _gather_124_type 1285 -#define _tmp_126_type 1286 -#define _loop0_127_type 1287 +#define _loop0_109_type 1268 +#define _gather_108_type 1269 +#define _tmp_110_type 1270 +#define _loop0_112_type 1271 +#define _gather_111_type 1272 +#define _loop0_114_type 1273 +#define _gather_113_type 1274 +#define _loop0_116_type 1275 +#define _gather_115_type 1276 +#define _loop0_118_type 1277 +#define _gather_117_type 1278 +#define _loop0_119_type 1279 +#define _loop0_121_type 1280 +#define _gather_120_type 1281 +#define _tmp_122_type 1282 +#define _loop0_124_type 1283 +#define _gather_123_type 1284 +#define _loop0_126_type 1285 +#define _gather_125_type 1286 +#define _tmp_127_type 1287 #define _loop0_128_type 1288 #define _loop0_129_type 1289 -#define _tmp_130_type 1290 +#define _loop0_130_type 1290 #define _tmp_131_type 1291 -#define _loop0_132_type 1292 -#define _tmp_133_type 1293 -#define _loop0_134_type 1294 -#define _tmp_135_type 1295 +#define _tmp_132_type 1292 +#define _loop0_133_type 1293 +#define _tmp_134_type 1294 +#define _loop0_135_type 1295 #define _tmp_136_type 1296 #define _tmp_137_type 1297 #define _tmp_138_type 1298 @@ -377,10 +377,12 @@ static KeywordToken *reserved_keywords[] = { #define _tmp_148_type 1308 #define _tmp_149_type 1309 #define _tmp_150_type 1310 -#define _loop1_151_type 1311 -#define _loop1_152_type 1312 -#define _tmp_153_type 1313 -#define _tmp_154_type 1314 +#define _tmp_151_type 1311 +#define _tmp_152_type 1312 +#define _loop1_153_type 1313 +#define _loop1_154_type 1314 +#define _tmp_155_type 1315 +#define _tmp_156_type 1316 static mod_ty file_rule(Parser *p); static mod_ty interactive_rule(Parser *p); @@ -650,34 +652,34 @@ static asdl_seq *_gather_103_rule(Parser *p); static asdl_seq *_loop1_105_rule(Parser *p); static asdl_seq *_loop0_106_rule(Parser *p); static asdl_seq *_loop0_107_rule(Parser *p); -static void *_tmp_108_rule(Parser *p); -static void *_tmp_109_rule(Parser *p); -static asdl_seq *_loop0_111_rule(Parser *p); -static asdl_seq *_gather_110_rule(Parser *p); -static asdl_seq *_loop0_113_rule(Parser *p); -static asdl_seq *_gather_112_rule(Parser *p); -static asdl_seq *_loop0_115_rule(Parser *p); -static asdl_seq *_gather_114_rule(Parser *p); -static asdl_seq *_loop0_117_rule(Parser *p); -static asdl_seq *_gather_116_rule(Parser *p); +static asdl_seq *_loop0_109_rule(Parser *p); +static asdl_seq *_gather_108_rule(Parser *p); +static void *_tmp_110_rule(Parser *p); +static asdl_seq *_loop0_112_rule(Parser *p); +static asdl_seq *_gather_111_rule(Parser *p); +static asdl_seq *_loop0_114_rule(Parser *p); +static asdl_seq *_gather_113_rule(Parser *p); +static asdl_seq *_loop0_116_rule(Parser *p); +static asdl_seq *_gather_115_rule(Parser *p); static asdl_seq *_loop0_118_rule(Parser *p); -static asdl_seq *_loop0_120_rule(Parser *p); -static asdl_seq *_gather_119_rule(Parser *p); -static void *_tmp_121_rule(Parser *p); -static asdl_seq *_loop0_123_rule(Parser *p); -static asdl_seq *_gather_122_rule(Parser *p); -static asdl_seq *_loop0_125_rule(Parser *p); -static asdl_seq *_gather_124_rule(Parser *p); -static void *_tmp_126_rule(Parser *p); -static asdl_seq *_loop0_127_rule(Parser *p); +static asdl_seq *_gather_117_rule(Parser *p); +static asdl_seq *_loop0_119_rule(Parser *p); +static asdl_seq *_loop0_121_rule(Parser *p); +static asdl_seq *_gather_120_rule(Parser *p); +static void *_tmp_122_rule(Parser *p); +static asdl_seq *_loop0_124_rule(Parser *p); +static asdl_seq *_gather_123_rule(Parser *p); +static asdl_seq *_loop0_126_rule(Parser *p); +static asdl_seq *_gather_125_rule(Parser *p); +static void *_tmp_127_rule(Parser *p); static asdl_seq *_loop0_128_rule(Parser *p); static asdl_seq *_loop0_129_rule(Parser *p); -static void *_tmp_130_rule(Parser *p); +static asdl_seq *_loop0_130_rule(Parser *p); static void *_tmp_131_rule(Parser *p); -static asdl_seq *_loop0_132_rule(Parser *p); -static void *_tmp_133_rule(Parser *p); -static asdl_seq *_loop0_134_rule(Parser *p); -static void *_tmp_135_rule(Parser *p); +static void *_tmp_132_rule(Parser *p); +static asdl_seq *_loop0_133_rule(Parser *p); +static void *_tmp_134_rule(Parser *p); +static asdl_seq *_loop0_135_rule(Parser *p); static void *_tmp_136_rule(Parser *p); static void *_tmp_137_rule(Parser *p); static void *_tmp_138_rule(Parser *p); @@ -693,10 +695,12 @@ static void *_tmp_147_rule(Parser *p); static void *_tmp_148_rule(Parser *p); static void *_tmp_149_rule(Parser *p); static void *_tmp_150_rule(Parser *p); -static asdl_seq *_loop1_151_rule(Parser *p); -static asdl_seq *_loop1_152_rule(Parser *p); -static void *_tmp_153_rule(Parser *p); -static void *_tmp_154_rule(Parser *p); +static void *_tmp_151_rule(Parser *p); +static void *_tmp_152_rule(Parser *p); +static asdl_seq *_loop1_153_rule(Parser *p); +static asdl_seq *_loop1_154_rule(Parser *p); +static void *_tmp_155_rule(Parser *p); +static void *_tmp_156_rule(Parser *p); // file: statements? $ @@ -12198,7 +12202,7 @@ arguments_rule(Parser *p) return _res; } -// args: starred_expression [',' args] | kwargs | named_expression [',' args] +// args: ','.(starred_expression | named_expression !'=')+ [',' kwargs] | kwargs static expr_ty args_rule(Parser *p) { @@ -12218,31 +12222,22 @@ args_rule(Parser *p) UNUSED(_start_lineno); // Only used by EXTRA macro int _start_col_offset = p->tokens[_mark]->col_offset; UNUSED(_start_col_offset); // Only used by EXTRA macro - { // starred_expression [',' args] + { // ','.(starred_expression | named_expression !'=')+ [',' kwargs] if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> args[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression [',' args]")); - expr_ty a; + D(fprintf(stderr, "%*c> args[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | named_expression !'=')+ [',' kwargs]")); + asdl_seq * a; void *b; if ( - (a = starred_expression_rule(p)) // starred_expression + (a = _gather_108_rule(p)) // ','.(starred_expression | named_expression !'=')+ && - (b = _tmp_108_rule(p), 1) // [',' args] + (b = _tmp_110_rule(p), 1) // [',' kwargs] ) { - D(fprintf(stderr, "%*c+ args[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression [',' args]")); - Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); - if (_token == NULL) { - D(p->level--); - return NULL; - } - int _end_lineno = _token->end_lineno; - UNUSED(_end_lineno); // Only used by EXTRA macro - int _end_col_offset = _token->end_col_offset; - UNUSED(_end_col_offset); // Only used by EXTRA macro - _res = _Py_Call ( _PyPegen_dummy_name ( p ) , ( b ) ? CHECK ( _PyPegen_seq_insert_in_front ( p , a , ( ( expr_ty ) b ) -> v . Call . args ) ) : CHECK ( _PyPegen_singleton_seq ( p , a ) ) , ( b ) ? ( ( expr_ty ) b ) -> v . Call . keywords : NULL , EXTRA ); + D(fprintf(stderr, "%*c+ args[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | named_expression !'=')+ [',' kwargs]")); + _res = _PyPegen_collect_call_seqs ( p , a , b ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; D(p->level--); @@ -12252,7 +12247,7 @@ args_rule(Parser *p) } p->mark = _mark; D(fprintf(stderr, "%*c%s args[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression [',' args]")); + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','.(starred_expression | named_expression !'=')+ [',' kwargs]")); } { // kwargs if (p->error_indicator) { @@ -12287,42 +12282,6 @@ args_rule(Parser *p) D(fprintf(stderr, "%*c%s args[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwargs")); } - { // named_expression [',' args] - if (p->error_indicator) { - D(p->level--); - return NULL; - } - D(fprintf(stderr, "%*c> args[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression [',' args]")); - expr_ty a; - void *b; - if ( - (a = named_expression_rule(p)) // named_expression - && - (b = _tmp_109_rule(p), 1) // [',' args] - ) - { - D(fprintf(stderr, "%*c+ args[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "named_expression [',' args]")); - Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); - if (_token == NULL) { - D(p->level--); - return NULL; - } - int _end_lineno = _token->end_lineno; - UNUSED(_end_lineno); // Only used by EXTRA macro - int _end_col_offset = _token->end_col_offset; - UNUSED(_end_col_offset); // Only used by EXTRA macro - _res = _Py_Call ( _PyPegen_dummy_name ( p ) , ( b ) ? CHECK ( _PyPegen_seq_insert_in_front ( p , a , ( ( expr_ty ) b ) -> v . Call . args ) ) : CHECK ( _PyPegen_singleton_seq ( p , a ) ) , ( b ) ? ( ( expr_ty ) b ) -> v . Call . keywords : NULL , EXTRA ); - if (_res == NULL && PyErr_Occurred()) { - p->error_indicator = 1; - D(p->level--); - return NULL; - } - goto done; - } - p->mark = _mark; - D(fprintf(stderr, "%*c%s args[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "named_expression [',' args]")); - } _res = NULL; done: D(p->level--); @@ -12353,11 +12312,11 @@ kwargs_rule(Parser *p) asdl_seq * a; asdl_seq * b; if ( - (a = _gather_110_rule(p)) // ','.kwarg_or_starred+ + (a = _gather_111_rule(p)) // ','.kwarg_or_starred+ && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (b = _gather_112_rule(p)) // ','.kwarg_or_double_starred+ + (b = _gather_113_rule(p)) // ','.kwarg_or_double_starred+ ) { D(fprintf(stderr, "%*c+ kwargs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+ ',' ','.kwarg_or_double_starred+")); @@ -12379,13 +12338,13 @@ kwargs_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> kwargs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+")); - asdl_seq * _gather_114_var; + asdl_seq * _gather_115_var; if ( - (_gather_114_var = _gather_114_rule(p)) // ','.kwarg_or_starred+ + (_gather_115_var = _gather_115_rule(p)) // ','.kwarg_or_starred+ ) { D(fprintf(stderr, "%*c+ kwargs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_starred+")); - _res = _gather_114_var; + _res = _gather_115_var; goto done; } p->mark = _mark; @@ -12398,13 +12357,13 @@ kwargs_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> kwargs[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_double_starred+")); - asdl_seq * _gather_116_var; + asdl_seq * _gather_117_var; if ( - (_gather_116_var = _gather_116_rule(p)) // ','.kwarg_or_double_starred+ + (_gather_117_var = _gather_117_rule(p)) // ','.kwarg_or_double_starred+ ) { D(fprintf(stderr, "%*c+ kwargs[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.kwarg_or_double_starred+")); - _res = _gather_116_var; + _res = _gather_117_var; goto done; } p->mark = _mark; @@ -12766,7 +12725,7 @@ star_targets_rule(Parser *p) if ( (a = star_target_rule(p)) // star_target && - (b = _loop0_118_rule(p)) // ((',' star_target))* + (b = _loop0_119_rule(p)) // ((',' star_target))* && (_opt_var = _PyPegen_expect_token(p, 12), 1) // ','? ) @@ -12820,7 +12779,7 @@ star_targets_seq_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_seq * a; if ( - (a = _gather_119_rule(p)) // ','.star_target+ + (a = _gather_120_rule(p)) // ','.star_target+ && (_opt_var = _PyPegen_expect_token(p, 12), 1) // ','? ) @@ -12883,7 +12842,7 @@ star_target_rule(Parser *p) if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (a = _tmp_121_rule(p)) // !'*' star_target + (a = _tmp_122_rule(p)) // !'*' star_target ) { D(fprintf(stderr, "%*c+ star_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (!'*' star_target)")); @@ -13405,7 +13364,7 @@ del_targets_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_seq * a; if ( - (a = _gather_122_rule(p)) // ','.del_target+ + (a = _gather_123_rule(p)) // ','.del_target+ && (_opt_var = _PyPegen_expect_token(p, 12), 1) // ','? ) @@ -13746,7 +13705,7 @@ targets_rule(Parser *p) UNUSED(_opt_var); // Silence compiler warnings asdl_seq * a; if ( - (a = _gather_124_rule(p)) // ','.target+ + (a = _gather_125_rule(p)) // ','.target+ && (_opt_var = _PyPegen_expect_token(p, 12), 1) // ','? ) @@ -14458,7 +14417,7 @@ incorrect_arguments_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_opt_var = _tmp_126_rule(p), 1) // [args | expression for_if_clauses] + (_opt_var = _tmp_127_rule(p), 1) // [args | expression for_if_clauses] ) { D(fprintf(stderr, "%*c+ incorrect_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses ',' [args | expression for_if_clauses]")); @@ -14716,7 +14675,7 @@ invalid_assignment_rule(Parser *p) D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions* ':' expression")); Token * _literal; Token * _literal_1; - asdl_seq * _loop0_127_var; + asdl_seq * _loop0_128_var; expr_ty a; expr_ty expression_var; if ( @@ -14724,7 +14683,7 @@ invalid_assignment_rule(Parser *p) && (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_loop0_127_var = _loop0_127_rule(p)) // star_named_expressions* + (_loop0_128_var = _loop0_128_rule(p)) // star_named_expressions* && (_literal_1 = _PyPegen_expect_token(p, 11)) // token=':' && @@ -14781,10 +14740,10 @@ invalid_assignment_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* star_expressions '='")); Token * _literal; - asdl_seq * _loop0_128_var; + asdl_seq * _loop0_129_var; expr_ty a; if ( - (_loop0_128_var = _loop0_128_rule(p)) // ((star_targets '='))* + (_loop0_129_var = _loop0_129_rule(p)) // ((star_targets '='))* && (a = star_expressions_rule(p)) // star_expressions && @@ -14811,10 +14770,10 @@ invalid_assignment_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* yield_expr '='")); Token * _literal; - asdl_seq * _loop0_129_var; + asdl_seq * _loop0_130_var; expr_ty a; if ( - (_loop0_129_var = _loop0_129_rule(p)) // ((star_targets '='))* + (_loop0_130_var = _loop0_130_rule(p)) // ((star_targets '='))* && (a = yield_expr_rule(p)) // yield_expr && @@ -14840,7 +14799,7 @@ invalid_assignment_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions augassign (yield_expr | star_expressions)")); - void *_tmp_130_var; + void *_tmp_131_var; expr_ty a; AugOperator* augassign_var; if ( @@ -14848,7 +14807,7 @@ invalid_assignment_rule(Parser *p) && (augassign_var = augassign_rule(p)) // augassign && - (_tmp_130_var = _tmp_130_rule(p)) // yield_expr | star_expressions + (_tmp_131_var = _tmp_131_rule(p)) // yield_expr | star_expressions ) { D(fprintf(stderr, "%*c+ invalid_assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions augassign (yield_expr | star_expressions)")); @@ -15059,11 +15018,11 @@ invalid_comprehension_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '(' | '{') starred_expression for_if_clauses")); - void *_tmp_131_var; + void *_tmp_132_var; expr_ty a; asdl_seq* for_if_clauses_var; if ( - (_tmp_131_var = _tmp_131_rule(p)) // '[' | '(' | '{' + (_tmp_132_var = _tmp_132_rule(p)) // '[' | '(' | '{' && (a = starred_expression_rule(p)) // starred_expression && @@ -15160,13 +15119,13 @@ invalid_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default* (slash_with_default | param_with_default+) param_no_default")); - asdl_seq * _loop0_132_var; - void *_tmp_133_var; + asdl_seq * _loop0_133_var; + void *_tmp_134_var; arg_ty param_no_default_var; if ( - (_loop0_132_var = _loop0_132_rule(p)) // param_no_default* + (_loop0_133_var = _loop0_133_rule(p)) // param_no_default* && - (_tmp_133_var = _tmp_133_rule(p)) // slash_with_default | param_with_default+ + (_tmp_134_var = _tmp_134_rule(p)) // slash_with_default | param_with_default+ && (param_no_default_var = param_no_default_rule(p)) // param_no_default ) @@ -15208,13 +15167,13 @@ invalid_lambda_parameters_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* (lambda_slash_with_default | lambda_param_with_default+) lambda_param_no_default")); - asdl_seq * _loop0_134_var; - void *_tmp_135_var; + asdl_seq * _loop0_135_var; + void *_tmp_136_var; arg_ty lambda_param_no_default_var; if ( - (_loop0_134_var = _loop0_134_rule(p)) // lambda_param_no_default* + (_loop0_135_var = _loop0_135_rule(p)) // lambda_param_no_default* && - (_tmp_135_var = _tmp_135_rule(p)) // lambda_slash_with_default | lambda_param_with_default+ + (_tmp_136_var = _tmp_136_rule(p)) // lambda_slash_with_default | lambda_param_with_default+ && (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default ) @@ -15256,11 +15215,11 @@ invalid_star_etc_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))")); Token * _literal; - void *_tmp_136_var; + void *_tmp_137_var; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_136_var = _tmp_136_rule(p)) // ')' | ',' (')' | '**') + (_tmp_137_var = _tmp_137_rule(p)) // ')' | ',' (')' | '**') ) { D(fprintf(stderr, "%*c+ invalid_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))")); @@ -15330,11 +15289,11 @@ invalid_lambda_star_etc_rule(Parser *p) } D(fprintf(stderr, "%*c> invalid_lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))")); Token * _literal; - void *_tmp_137_var; + void *_tmp_138_var; if ( (_literal = _PyPegen_expect_token(p, 16)) // token='*' && - (_tmp_137_var = _tmp_137_rule(p)) // ':' | ',' (':' | '**') + (_tmp_138_var = _tmp_138_rule(p)) // ':' | ',' (':' | '**') ) { D(fprintf(stderr, "%*c+ invalid_lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))")); @@ -16843,12 +16802,12 @@ _loop1_22_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_22[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_138_var; + void *_tmp_139_var; while ( - (_tmp_138_var = _tmp_138_rule(p)) // star_targets '=' + (_tmp_139_var = _tmp_139_rule(p)) // star_targets '=' ) { - _res = _tmp_138_var; + _res = _tmp_139_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -17351,12 +17310,12 @@ _loop0_31_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop0_31[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); - void *_tmp_139_var; + void *_tmp_140_var; while ( - (_tmp_139_var = _tmp_139_rule(p)) // '.' | '...' + (_tmp_140_var = _tmp_140_rule(p)) // '.' | '...' ) { - _res = _tmp_139_var; + _res = _tmp_140_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -17417,12 +17376,12 @@ _loop1_32_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_32[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')")); - void *_tmp_140_var; + void *_tmp_141_var; while ( - (_tmp_140_var = _tmp_140_rule(p)) // '.' | '...' + (_tmp_141_var = _tmp_141_rule(p)) // '.' | '...' ) { - _res = _tmp_140_var; + _res = _tmp_141_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -19579,12 +19538,12 @@ _loop1_68_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_68[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('@' named_expression NEWLINE)")); - void *_tmp_141_var; + void *_tmp_142_var; while ( - (_tmp_141_var = _tmp_141_rule(p)) // '@' named_expression NEWLINE + (_tmp_142_var = _tmp_142_rule(p)) // '@' named_expression NEWLINE ) { - _res = _tmp_141_var; + _res = _tmp_142_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -19811,12 +19770,12 @@ _loop1_72_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_72[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_expression)")); - void *_tmp_142_var; + void *_tmp_143_var; while ( - (_tmp_142_var = _tmp_142_rule(p)) // ',' star_expression + (_tmp_143_var = _tmp_143_rule(p)) // ',' star_expression ) { - _res = _tmp_142_var; + _res = _tmp_143_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -19996,12 +19955,12 @@ _loop1_75_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_75[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' expression)")); - void *_tmp_143_var; + void *_tmp_144_var; while ( - (_tmp_143_var = _tmp_143_rule(p)) // ',' expression + (_tmp_144_var = _tmp_144_rule(p)) // ',' expression ) { - _res = _tmp_143_var; + _res = _tmp_144_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -21026,12 +20985,12 @@ _loop1_90_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_90[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('or' conjunction)")); - void *_tmp_144_var; + void *_tmp_145_var; while ( - (_tmp_144_var = _tmp_144_rule(p)) // 'or' conjunction + (_tmp_145_var = _tmp_145_rule(p)) // 'or' conjunction ) { - _res = _tmp_144_var; + _res = _tmp_145_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -21097,12 +21056,12 @@ _loop1_91_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop1_91[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('and' inversion)")); - void *_tmp_145_var; + void *_tmp_146_var; while ( - (_tmp_145_var = _tmp_145_rule(p)) // 'and' inversion + (_tmp_146_var = _tmp_146_rule(p)) // 'and' inversion ) { - _res = _tmp_145_var; + _res = _tmp_146_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -22018,12 +21977,12 @@ _loop0_106_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop0_106[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); - void *_tmp_146_var; + void *_tmp_147_var; while ( - (_tmp_146_var = _tmp_146_rule(p)) // 'if' disjunction + (_tmp_147_var = _tmp_147_rule(p)) // 'if' disjunction ) { - _res = _tmp_146_var; + _res = _tmp_147_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -22084,12 +22043,12 @@ _loop0_107_rule(Parser *p) return NULL; } D(fprintf(stderr, "%*c> _loop0_107[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)")); - void *_tmp_147_var; + void *_tmp_148_var; while ( - (_tmp_147_var = _tmp_147_rule(p)) // 'if' disjunction + (_tmp_148_var = _tmp_148_rule(p)) // 'if' disjunction ) { - _res = _tmp_147_var; + _res = _tmp_148_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -22123,43 +22082,113 @@ _loop0_107_rule(Parser *p) return _seq; } -// _tmp_108: ',' args -static void * -_tmp_108_rule(Parser *p) +// _loop0_109: ',' (starred_expression | named_expression !'=') +static asdl_seq * +_loop0_109_rule(Parser *p) { D(p->level++); if (p->error_indicator) { D(p->level--); return NULL; } - void * _res = NULL; + void *_res = NULL; int _mark = p->mark; - { // ',' args + int _start_mark = p->mark; + void **_children = PyMem_Malloc(sizeof(void *)); + if (!_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + ssize_t _children_capacity = 1; + ssize_t _n = 0; + { // ',' (starred_expression | named_expression !'=') if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_108[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' args")); + D(fprintf(stderr, "%*c> _loop0_109[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (starred_expression | named_expression !'=')")); Token * _literal; - expr_ty c; - if ( + void *elem; + while ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (c = args_rule(p)) // args + (elem = _tmp_149_rule(p)) // starred_expression | named_expression !'=' ) { - D(fprintf(stderr, "%*c+ _tmp_108[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' args")); - _res = c; + _res = elem; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; + PyMem_Free(_children); D(p->level--); return NULL; } + if (_n == _children_capacity) { + _children_capacity *= 2; + void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); + if (!_new_children) { + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + _children = _new_children; + } + _children[_n++] = _res; + _mark = p->mark; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _loop0_109[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (starred_expression | named_expression !'=')")); + } + asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); + if (!_seq) { + PyMem_Free(_children); + p->error_indicator = 1; + PyErr_NoMemory(); + D(p->level--); + return NULL; + } + for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); + PyMem_Free(_children); + _PyPegen_insert_memo(p, _start_mark, _loop0_109_type, _seq); + D(p->level--); + return _seq; +} + +// _gather_108: (starred_expression | named_expression !'=') _loop0_109 +static asdl_seq * +_gather_108_rule(Parser *p) +{ + D(p->level++); + if (p->error_indicator) { + D(p->level--); + return NULL; + } + asdl_seq * _res = NULL; + int _mark = p->mark; + { // (starred_expression | named_expression !'=') _loop0_109 + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> _gather_108[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(starred_expression | named_expression !'=') _loop0_109")); + void *elem; + asdl_seq * seq; + if ( + (elem = _tmp_149_rule(p)) // starred_expression | named_expression !'=' + && + (seq = _loop0_109_rule(p)) // _loop0_109 + ) + { + D(fprintf(stderr, "%*c+ _gather_108[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "(starred_expression | named_expression !'=') _loop0_109")); + _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_108[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' args")); + D(fprintf(stderr, "%*c%s _gather_108[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(starred_expression | named_expression !'=') _loop0_109")); } _res = NULL; done: @@ -22167,9 +22196,9 @@ _tmp_108_rule(Parser *p) return _res; } -// _tmp_109: ',' args +// _tmp_110: ',' kwargs static void * -_tmp_109_rule(Parser *p) +_tmp_110_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -22178,22 +22207,22 @@ _tmp_109_rule(Parser *p) } void * _res = NULL; int _mark = p->mark; - { // ',' args + { // ',' kwargs if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_109[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' args")); + D(fprintf(stderr, "%*c> _tmp_110[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwargs")); Token * _literal; - expr_ty c; + asdl_seq* k; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (c = args_rule(p)) // args + (k = kwargs_rule(p)) // kwargs ) { - D(fprintf(stderr, "%*c+ _tmp_109[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' args")); - _res = c; + D(fprintf(stderr, "%*c+ _tmp_110[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' kwargs")); + _res = k; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; D(p->level--); @@ -22202,8 +22231,8 @@ _tmp_109_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_109[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' args")); + D(fprintf(stderr, "%*c%s _tmp_110[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwargs")); } _res = NULL; done: @@ -22211,9 +22240,9 @@ _tmp_109_rule(Parser *p) return _res; } -// _loop0_111: ',' kwarg_or_starred +// _loop0_112: ',' kwarg_or_starred static asdl_seq * -_loop0_111_rule(Parser *p) +_loop0_112_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -22237,7 +22266,7 @@ _loop0_111_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_111[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); + D(fprintf(stderr, "%*c> _loop0_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); Token * _literal; KeywordOrStarred* elem; while ( @@ -22268,7 +22297,7 @@ _loop0_111_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_111[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_112[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_starred")); } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -22281,14 +22310,14 @@ _loop0_111_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_111_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_112_type, _seq); D(p->level--); return _seq; } -// _gather_110: kwarg_or_starred _loop0_111 +// _gather_111: kwarg_or_starred _loop0_112 static asdl_seq * -_gather_110_rule(Parser *p) +_gather_111_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -22297,27 +22326,27 @@ _gather_110_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // kwarg_or_starred _loop0_111 + { // kwarg_or_starred _loop0_112 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_110[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_111")); + D(fprintf(stderr, "%*c> _gather_111[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_112")); KeywordOrStarred* elem; asdl_seq * seq; if ( (elem = kwarg_or_starred_rule(p)) // kwarg_or_starred && - (seq = _loop0_111_rule(p)) // _loop0_111 + (seq = _loop0_112_rule(p)) // _loop0_112 ) { - D(fprintf(stderr, "%*c+ _gather_110[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_111")); + D(fprintf(stderr, "%*c+ _gather_111[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_112")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_110[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_111")); + D(fprintf(stderr, "%*c%s _gather_111[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_112")); } _res = NULL; done: @@ -22325,9 +22354,9 @@ _gather_110_rule(Parser *p) return _res; } -// _loop0_113: ',' kwarg_or_double_starred +// _loop0_114: ',' kwarg_or_double_starred static asdl_seq * -_loop0_113_rule(Parser *p) +_loop0_114_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -22351,7 +22380,7 @@ _loop0_113_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); + D(fprintf(stderr, "%*c> _loop0_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); Token * _literal; KeywordOrStarred* elem; while ( @@ -22382,7 +22411,7 @@ _loop0_113_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_113[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_114[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_double_starred")); } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -22395,14 +22424,14 @@ _loop0_113_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_113_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_114_type, _seq); D(p->level--); return _seq; } -// _gather_112: kwarg_or_double_starred _loop0_113 +// _gather_113: kwarg_or_double_starred _loop0_114 static asdl_seq * -_gather_112_rule(Parser *p) +_gather_113_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -22411,27 +22440,27 @@ _gather_112_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // kwarg_or_double_starred _loop0_113 + { // kwarg_or_double_starred _loop0_114 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_112[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_113")); + D(fprintf(stderr, "%*c> _gather_113[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_114")); KeywordOrStarred* elem; asdl_seq * seq; if ( (elem = kwarg_or_double_starred_rule(p)) // kwarg_or_double_starred && - (seq = _loop0_113_rule(p)) // _loop0_113 + (seq = _loop0_114_rule(p)) // _loop0_114 ) { - D(fprintf(stderr, "%*c+ _gather_112[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_113")); + D(fprintf(stderr, "%*c+ _gather_113[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_114")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_112[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_113")); + D(fprintf(stderr, "%*c%s _gather_113[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_114")); } _res = NULL; done: @@ -22439,9 +22468,9 @@ _gather_112_rule(Parser *p) return _res; } -// _loop0_115: ',' kwarg_or_starred +// _loop0_116: ',' kwarg_or_starred static asdl_seq * -_loop0_115_rule(Parser *p) +_loop0_116_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -22465,7 +22494,7 @@ _loop0_115_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_115[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); + D(fprintf(stderr, "%*c> _loop0_116[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_starred")); Token * _literal; KeywordOrStarred* elem; while ( @@ -22496,7 +22525,7 @@ _loop0_115_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_115[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_116[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_starred")); } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -22509,14 +22538,14 @@ _loop0_115_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_115_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_116_type, _seq); D(p->level--); return _seq; } -// _gather_114: kwarg_or_starred _loop0_115 +// _gather_115: kwarg_or_starred _loop0_116 static asdl_seq * -_gather_114_rule(Parser *p) +_gather_115_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -22525,27 +22554,27 @@ _gather_114_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // kwarg_or_starred _loop0_115 + { // kwarg_or_starred _loop0_116 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_114[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_115")); + D(fprintf(stderr, "%*c> _gather_115[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_116")); KeywordOrStarred* elem; asdl_seq * seq; if ( (elem = kwarg_or_starred_rule(p)) // kwarg_or_starred && - (seq = _loop0_115_rule(p)) // _loop0_115 + (seq = _loop0_116_rule(p)) // _loop0_116 ) { - D(fprintf(stderr, "%*c+ _gather_114[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_115")); + D(fprintf(stderr, "%*c+ _gather_115[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_starred _loop0_116")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_114[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_115")); + D(fprintf(stderr, "%*c%s _gather_115[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_starred _loop0_116")); } _res = NULL; done: @@ -22553,9 +22582,9 @@ _gather_114_rule(Parser *p) return _res; } -// _loop0_117: ',' kwarg_or_double_starred +// _loop0_118: ',' kwarg_or_double_starred static asdl_seq * -_loop0_117_rule(Parser *p) +_loop0_118_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -22579,7 +22608,7 @@ _loop0_117_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); + D(fprintf(stderr, "%*c> _loop0_118[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' kwarg_or_double_starred")); Token * _literal; KeywordOrStarred* elem; while ( @@ -22610,7 +22639,7 @@ _loop0_117_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_117[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_118[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' kwarg_or_double_starred")); } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -22623,14 +22652,14 @@ _loop0_117_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_117_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_118_type, _seq); D(p->level--); return _seq; } -// _gather_116: kwarg_or_double_starred _loop0_117 +// _gather_117: kwarg_or_double_starred _loop0_118 static asdl_seq * -_gather_116_rule(Parser *p) +_gather_117_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -22639,27 +22668,27 @@ _gather_116_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // kwarg_or_double_starred _loop0_117 + { // kwarg_or_double_starred _loop0_118 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_116[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_117")); + D(fprintf(stderr, "%*c> _gather_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_118")); KeywordOrStarred* elem; asdl_seq * seq; if ( (elem = kwarg_or_double_starred_rule(p)) // kwarg_or_double_starred && - (seq = _loop0_117_rule(p)) // _loop0_117 + (seq = _loop0_118_rule(p)) // _loop0_118 ) { - D(fprintf(stderr, "%*c+ _gather_116[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_117")); + D(fprintf(stderr, "%*c+ _gather_117[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "kwarg_or_double_starred _loop0_118")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_116[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_117")); + D(fprintf(stderr, "%*c%s _gather_117[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "kwarg_or_double_starred _loop0_118")); } _res = NULL; done: @@ -22667,9 +22696,9 @@ _gather_116_rule(Parser *p) return _res; } -// _loop0_118: (',' star_target) +// _loop0_119: (',' star_target) static asdl_seq * -_loop0_118_rule(Parser *p) +_loop0_119_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -22693,13 +22722,13 @@ _loop0_118_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_118[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); - void *_tmp_148_var; + D(fprintf(stderr, "%*c> _loop0_119[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)")); + void *_tmp_150_var; while ( - (_tmp_148_var = _tmp_148_rule(p)) // ',' star_target + (_tmp_150_var = _tmp_150_rule(p)) // ',' star_target ) { - _res = _tmp_148_var; + _res = _tmp_150_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -22715,7 +22744,7 @@ _loop0_118_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_118[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_119[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' star_target)")); } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -22728,14 +22757,14 @@ _loop0_118_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_118_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_119_type, _seq); D(p->level--); return _seq; } -// _loop0_120: ',' star_target +// _loop0_121: ',' star_target static asdl_seq * -_loop0_120_rule(Parser *p) +_loop0_121_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -22759,7 +22788,7 @@ _loop0_120_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_120[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c> _loop0_121[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); Token * _literal; expr_ty elem; while ( @@ -22790,7 +22819,7 @@ _loop0_120_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_120[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_121[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -22803,14 +22832,14 @@ _loop0_120_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_120_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_121_type, _seq); D(p->level--); return _seq; } -// _gather_119: star_target _loop0_120 +// _gather_120: star_target _loop0_121 static asdl_seq * -_gather_119_rule(Parser *p) +_gather_120_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -22819,27 +22848,27 @@ _gather_119_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // star_target _loop0_120 + { // star_target _loop0_121 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_119[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target _loop0_120")); + D(fprintf(stderr, "%*c> _gather_120[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target _loop0_121")); expr_ty elem; asdl_seq * seq; if ( (elem = star_target_rule(p)) // star_target && - (seq = _loop0_120_rule(p)) // _loop0_120 + (seq = _loop0_121_rule(p)) // _loop0_121 ) { - D(fprintf(stderr, "%*c+ _gather_119[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target _loop0_120")); + D(fprintf(stderr, "%*c+ _gather_120[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target _loop0_121")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_119[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_target _loop0_120")); + D(fprintf(stderr, "%*c%s _gather_120[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_target _loop0_121")); } _res = NULL; done: @@ -22847,9 +22876,9 @@ _gather_119_rule(Parser *p) return _res; } -// _tmp_121: !'*' star_target +// _tmp_122: !'*' star_target static void * -_tmp_121_rule(Parser *p) +_tmp_122_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -22863,7 +22892,7 @@ _tmp_121_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_121[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); + D(fprintf(stderr, "%*c> _tmp_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); expr_ty star_target_var; if ( _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 16) // token='*' @@ -22871,12 +22900,12 @@ _tmp_121_rule(Parser *p) (star_target_var = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_121[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); + D(fprintf(stderr, "%*c+ _tmp_122[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!'*' star_target")); _res = star_target_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_121[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_122[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "!'*' star_target")); } _res = NULL; @@ -22885,9 +22914,9 @@ _tmp_121_rule(Parser *p) return _res; } -// _loop0_123: ',' del_target +// _loop0_124: ',' del_target static asdl_seq * -_loop0_123_rule(Parser *p) +_loop0_124_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -22911,7 +22940,7 @@ _loop0_123_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' del_target")); + D(fprintf(stderr, "%*c> _loop0_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' del_target")); Token * _literal; expr_ty elem; while ( @@ -22942,7 +22971,7 @@ _loop0_123_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_123[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_124[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' del_target")); } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -22955,14 +22984,14 @@ _loop0_123_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_123_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_124_type, _seq); D(p->level--); return _seq; } -// _gather_122: del_target _loop0_123 +// _gather_123: del_target _loop0_124 static asdl_seq * -_gather_122_rule(Parser *p) +_gather_123_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -22971,27 +23000,27 @@ _gather_122_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // del_target _loop0_123 + { // del_target _loop0_124 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "del_target _loop0_123")); + D(fprintf(stderr, "%*c> _gather_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "del_target _loop0_124")); expr_ty elem; asdl_seq * seq; if ( (elem = del_target_rule(p)) // del_target && - (seq = _loop0_123_rule(p)) // _loop0_123 + (seq = _loop0_124_rule(p)) // _loop0_124 ) { - D(fprintf(stderr, "%*c+ _gather_122[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "del_target _loop0_123")); + D(fprintf(stderr, "%*c+ _gather_123[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "del_target _loop0_124")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_122[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "del_target _loop0_123")); + D(fprintf(stderr, "%*c%s _gather_123[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "del_target _loop0_124")); } _res = NULL; done: @@ -22999,9 +23028,9 @@ _gather_122_rule(Parser *p) return _res; } -// _loop0_125: ',' target +// _loop0_126: ',' target static asdl_seq * -_loop0_125_rule(Parser *p) +_loop0_126_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -23025,7 +23054,7 @@ _loop0_125_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' target")); + D(fprintf(stderr, "%*c> _loop0_126[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' target")); Token * _literal; expr_ty elem; while ( @@ -23056,7 +23085,7 @@ _loop0_125_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_125[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_126[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' target")); } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -23069,14 +23098,14 @@ _loop0_125_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_125_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_126_type, _seq); D(p->level--); return _seq; } -// _gather_124: target _loop0_125 +// _gather_125: target _loop0_126 static asdl_seq * -_gather_124_rule(Parser *p) +_gather_125_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -23085,27 +23114,27 @@ _gather_124_rule(Parser *p) } asdl_seq * _res = NULL; int _mark = p->mark; - { // target _loop0_125 + { // target _loop0_126 if (p->error_indicator) { D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _gather_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "target _loop0_125")); + D(fprintf(stderr, "%*c> _gather_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "target _loop0_126")); expr_ty elem; asdl_seq * seq; if ( (elem = target_rule(p)) // target && - (seq = _loop0_125_rule(p)) // _loop0_125 + (seq = _loop0_126_rule(p)) // _loop0_126 ) { - D(fprintf(stderr, "%*c+ _gather_124[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "target _loop0_125")); + D(fprintf(stderr, "%*c+ _gather_125[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "target _loop0_126")); _res = _PyPegen_seq_insert_in_front(p, elem, seq); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _gather_124[%d-%d]: %s failed!\n", p->level, ' ', - p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "target _loop0_125")); + D(fprintf(stderr, "%*c%s _gather_125[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "target _loop0_126")); } _res = NULL; done: @@ -23113,9 +23142,9 @@ _gather_124_rule(Parser *p) return _res; } -// _tmp_126: args | expression for_if_clauses +// _tmp_127: args | expression for_if_clauses static void * -_tmp_126_rule(Parser *p) +_tmp_127_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -23129,18 +23158,18 @@ _tmp_126_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_126[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args")); + D(fprintf(stderr, "%*c> _tmp_127[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args")); expr_ty args_var; if ( (args_var = args_rule(p)) // args ) { - D(fprintf(stderr, "%*c+ _tmp_126[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args")); + D(fprintf(stderr, "%*c+ _tmp_127[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args")); _res = args_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_126[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_127[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "args")); } { // expression for_if_clauses @@ -23148,7 +23177,7 @@ _tmp_126_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_126[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); + D(fprintf(stderr, "%*c> _tmp_127[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); expr_ty expression_var; asdl_seq* for_if_clauses_var; if ( @@ -23157,12 +23186,12 @@ _tmp_126_rule(Parser *p) (for_if_clauses_var = for_if_clauses_rule(p)) // for_if_clauses ) { - D(fprintf(stderr, "%*c+ _tmp_126[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); + D(fprintf(stderr, "%*c+ _tmp_127[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses")); _res = _PyPegen_dummy_name(p, expression_var, for_if_clauses_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_126[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_127[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression for_if_clauses")); } _res = NULL; @@ -23171,9 +23200,9 @@ _tmp_126_rule(Parser *p) return _res; } -// _loop0_127: star_named_expressions +// _loop0_128: star_named_expressions static asdl_seq * -_loop0_127_rule(Parser *p) +_loop0_128_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -23197,7 +23226,7 @@ _loop0_127_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_127[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expressions")); + D(fprintf(stderr, "%*c> _loop0_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expressions")); asdl_seq* star_named_expressions_var; while ( (star_named_expressions_var = star_named_expressions_rule(p)) // star_named_expressions @@ -23219,7 +23248,7 @@ _loop0_127_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_127[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_128[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expressions")); } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -23232,14 +23261,14 @@ _loop0_127_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_127_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_128_type, _seq); D(p->level--); return _seq; } -// _loop0_128: (star_targets '=') +// _loop0_129: (star_targets '=') static asdl_seq * -_loop0_128_rule(Parser *p) +_loop0_129_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -23263,13 +23292,13 @@ _loop0_128_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_149_var; + D(fprintf(stderr, "%*c> _loop0_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); + void *_tmp_151_var; while ( - (_tmp_149_var = _tmp_149_rule(p)) // star_targets '=' + (_tmp_151_var = _tmp_151_rule(p)) // star_targets '=' ) { - _res = _tmp_149_var; + _res = _tmp_151_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -23285,7 +23314,7 @@ _loop0_128_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_128[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_129[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(star_targets '=')")); } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -23298,14 +23327,14 @@ _loop0_128_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_128_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_129_type, _seq); D(p->level--); return _seq; } -// _loop0_129: (star_targets '=') +// _loop0_130: (star_targets '=') static asdl_seq * -_loop0_129_rule(Parser *p) +_loop0_130_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -23329,13 +23358,13 @@ _loop0_129_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); - void *_tmp_150_var; + D(fprintf(stderr, "%*c> _loop0_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')")); + void *_tmp_152_var; while ( - (_tmp_150_var = _tmp_150_rule(p)) // star_targets '=' + (_tmp_152_var = _tmp_152_rule(p)) // star_targets '=' ) { - _res = _tmp_150_var; + _res = _tmp_152_var; if (_n == _children_capacity) { _children_capacity *= 2; void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *)); @@ -23351,7 +23380,7 @@ _loop0_129_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_129[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_130[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(star_targets '=')")); } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -23364,14 +23393,14 @@ _loop0_129_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_129_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_130_type, _seq); D(p->level--); return _seq; } -// _tmp_130: yield_expr | star_expressions +// _tmp_131: yield_expr | star_expressions static void * -_tmp_130_rule(Parser *p) +_tmp_131_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -23385,18 +23414,18 @@ _tmp_130_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c> _tmp_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr")); expr_ty yield_expr_var; if ( (yield_expr_var = yield_expr_rule(p)) // yield_expr ) { - D(fprintf(stderr, "%*c+ _tmp_130[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); + D(fprintf(stderr, "%*c+ _tmp_131[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr")); _res = yield_expr_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_130[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_131[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr")); } { // star_expressions @@ -23404,18 +23433,18 @@ _tmp_130_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c> _tmp_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions")); expr_ty star_expressions_var; if ( (star_expressions_var = star_expressions_rule(p)) // star_expressions ) { - D(fprintf(stderr, "%*c+ _tmp_130[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); + D(fprintf(stderr, "%*c+ _tmp_131[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions")); _res = star_expressions_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_130[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_131[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions")); } _res = NULL; @@ -23424,9 +23453,9 @@ _tmp_130_rule(Parser *p) return _res; } -// _tmp_131: '[' | '(' | '{' +// _tmp_132: '[' | '(' | '{' static void * -_tmp_131_rule(Parser *p) +_tmp_132_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -23440,18 +23469,18 @@ _tmp_131_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c> _tmp_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 9)) // token='[' ) { - D(fprintf(stderr, "%*c+ _tmp_131[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); + D(fprintf(stderr, "%*c+ _tmp_132[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_131[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_132[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['")); } { // '(' @@ -23459,18 +23488,18 @@ _tmp_131_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); + D(fprintf(stderr, "%*c> _tmp_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 7)) // token='(' ) { - D(fprintf(stderr, "%*c+ _tmp_131[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); + D(fprintf(stderr, "%*c+ _tmp_132[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_131[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_132[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'('")); } { // '{' @@ -23478,18 +23507,18 @@ _tmp_131_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c> _tmp_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 25)) // token='{' ) { - D(fprintf(stderr, "%*c+ _tmp_131[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); + D(fprintf(stderr, "%*c+ _tmp_132[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_131[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_132[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'")); } _res = NULL; @@ -23498,9 +23527,9 @@ _tmp_131_rule(Parser *p) return _res; } -// _loop0_132: param_no_default +// _loop0_133: param_no_default static asdl_seq * -_loop0_132_rule(Parser *p) +_loop0_133_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -23524,7 +23553,7 @@ _loop0_132_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); + D(fprintf(stderr, "%*c> _loop0_133[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default")); arg_ty param_no_default_var; while ( (param_no_default_var = param_no_default_rule(p)) // param_no_default @@ -23546,7 +23575,7 @@ _loop0_132_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_132[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_133[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default")); } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -23559,14 +23588,14 @@ _loop0_132_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_132_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_133_type, _seq); D(p->level--); return _seq; } -// _tmp_133: slash_with_default | param_with_default+ +// _tmp_134: slash_with_default | param_with_default+ static void * -_tmp_133_rule(Parser *p) +_tmp_134_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -23580,18 +23609,18 @@ _tmp_133_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_133[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default")); + D(fprintf(stderr, "%*c> _tmp_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default")); SlashWithDefault* slash_with_default_var; if ( (slash_with_default_var = slash_with_default_rule(p)) // slash_with_default ) { - D(fprintf(stderr, "%*c+ _tmp_133[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_with_default")); + D(fprintf(stderr, "%*c+ _tmp_134[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_with_default")); _res = slash_with_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_133[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_134[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slash_with_default")); } { // param_with_default+ @@ -23599,18 +23628,18 @@ _tmp_133_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_133[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default+")); - asdl_seq * _loop1_151_var; + D(fprintf(stderr, "%*c> _tmp_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default+")); + asdl_seq * _loop1_153_var; if ( - (_loop1_151_var = _loop1_151_rule(p)) // param_with_default+ + (_loop1_153_var = _loop1_153_rule(p)) // param_with_default+ ) { - D(fprintf(stderr, "%*c+ _tmp_133[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_with_default+")); - _res = _loop1_151_var; + D(fprintf(stderr, "%*c+ _tmp_134[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_with_default+")); + _res = _loop1_153_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_133[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_134[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default+")); } _res = NULL; @@ -23619,9 +23648,9 @@ _tmp_133_rule(Parser *p) return _res; } -// _loop0_134: lambda_param_no_default +// _loop0_135: lambda_param_no_default static asdl_seq * -_loop0_134_rule(Parser *p) +_loop0_135_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -23645,7 +23674,7 @@ _loop0_134_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop0_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); + D(fprintf(stderr, "%*c> _loop0_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default")); arg_ty lambda_param_no_default_var; while ( (lambda_param_no_default_var = lambda_param_no_default_rule(p)) // lambda_param_no_default @@ -23667,7 +23696,7 @@ _loop0_134_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop0_134[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop0_135[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default")); } asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena); @@ -23680,14 +23709,14 @@ _loop0_134_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop0_134_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop0_135_type, _seq); D(p->level--); return _seq; } -// _tmp_135: lambda_slash_with_default | lambda_param_with_default+ +// _tmp_136: lambda_slash_with_default | lambda_param_with_default+ static void * -_tmp_135_rule(Parser *p) +_tmp_136_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -23701,18 +23730,18 @@ _tmp_135_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); + D(fprintf(stderr, "%*c> _tmp_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); SlashWithDefault* lambda_slash_with_default_var; if ( (lambda_slash_with_default_var = lambda_slash_with_default_rule(p)) // lambda_slash_with_default ) { - D(fprintf(stderr, "%*c+ _tmp_135[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); + D(fprintf(stderr, "%*c+ _tmp_136[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default")); _res = lambda_slash_with_default_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_135[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_136[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_slash_with_default")); } { // lambda_param_with_default+ @@ -23720,18 +23749,18 @@ _tmp_135_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+")); - asdl_seq * _loop1_152_var; + D(fprintf(stderr, "%*c> _tmp_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+")); + asdl_seq * _loop1_154_var; if ( - (_loop1_152_var = _loop1_152_rule(p)) // lambda_param_with_default+ + (_loop1_154_var = _loop1_154_rule(p)) // lambda_param_with_default+ ) { - D(fprintf(stderr, "%*c+ _tmp_135[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+")); - _res = _loop1_152_var; + D(fprintf(stderr, "%*c+ _tmp_136[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+")); + _res = _loop1_154_var; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_135[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_136[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default+")); } _res = NULL; @@ -23740,9 +23769,9 @@ _tmp_135_rule(Parser *p) return _res; } -// _tmp_136: ')' | ',' (')' | '**') +// _tmp_137: ')' | ',' (')' | '**') static void * -_tmp_136_rule(Parser *p) +_tmp_137_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -23756,18 +23785,18 @@ _tmp_136_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_136[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_137[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_136[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_137[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // ',' (')' | '**') @@ -23775,21 +23804,21 @@ _tmp_136_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); + D(fprintf(stderr, "%*c> _tmp_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); Token * _literal; - void *_tmp_153_var; + void *_tmp_155_var; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_tmp_153_var = _tmp_153_rule(p)) // ')' | '**' + (_tmp_155_var = _tmp_155_rule(p)) // ')' | '**' ) { - D(fprintf(stderr, "%*c+ _tmp_136[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); - _res = _PyPegen_dummy_name(p, _literal, _tmp_153_var); + D(fprintf(stderr, "%*c+ _tmp_137[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')")); + _res = _PyPegen_dummy_name(p, _literal, _tmp_155_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_136[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_137[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (')' | '**')")); } _res = NULL; @@ -23798,9 +23827,9 @@ _tmp_136_rule(Parser *p) return _res; } -// _tmp_137: ':' | ',' (':' | '**') +// _tmp_138: ':' | ',' (':' | '**') static void * -_tmp_137_rule(Parser *p) +_tmp_138_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -23814,18 +23843,18 @@ _tmp_137_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_137[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_138[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_137[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_138[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // ',' (':' | '**') @@ -23833,21 +23862,21 @@ _tmp_137_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); + D(fprintf(stderr, "%*c> _tmp_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); Token * _literal; - void *_tmp_154_var; + void *_tmp_156_var; if ( (_literal = _PyPegen_expect_token(p, 12)) // token=',' && - (_tmp_154_var = _tmp_154_rule(p)) // ':' | '**' + (_tmp_156_var = _tmp_156_rule(p)) // ':' | '**' ) { - D(fprintf(stderr, "%*c+ _tmp_137[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); - _res = _PyPegen_dummy_name(p, _literal, _tmp_154_var); + D(fprintf(stderr, "%*c+ _tmp_138[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')")); + _res = _PyPegen_dummy_name(p, _literal, _tmp_156_var); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_137[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_138[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (':' | '**')")); } _res = NULL; @@ -23856,9 +23885,9 @@ _tmp_137_rule(Parser *p) return _res; } -// _tmp_138: star_targets '=' +// _tmp_139: star_targets '=' static void * -_tmp_138_rule(Parser *p) +_tmp_139_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -23872,7 +23901,7 @@ _tmp_138_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty z; if ( @@ -23881,7 +23910,7 @@ _tmp_138_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_138[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_139[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -23891,7 +23920,7 @@ _tmp_138_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_138[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_139[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; @@ -23900,9 +23929,9 @@ _tmp_138_rule(Parser *p) return _res; } -// _tmp_139: '.' | '...' +// _tmp_140: '.' | '...' static void * -_tmp_139_rule(Parser *p) +_tmp_140_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -23916,18 +23945,18 @@ _tmp_139_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c> _tmp_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 23)) // token='.' ) { - D(fprintf(stderr, "%*c+ _tmp_139[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c+ _tmp_140[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_139[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_140[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); } { // '...' @@ -23935,18 +23964,18 @@ _tmp_139_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c> _tmp_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 52)) // token='...' ) { - D(fprintf(stderr, "%*c+ _tmp_139[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c+ _tmp_140[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_139[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_140[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'")); } _res = NULL; @@ -23955,9 +23984,9 @@ _tmp_139_rule(Parser *p) return _res; } -// _tmp_140: '.' | '...' +// _tmp_141: '.' | '...' static void * -_tmp_140_rule(Parser *p) +_tmp_141_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -23971,18 +24000,18 @@ _tmp_140_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c> _tmp_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 23)) // token='.' ) { - D(fprintf(stderr, "%*c+ _tmp_140[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); + D(fprintf(stderr, "%*c+ _tmp_141[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_140[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_141[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'")); } { // '...' @@ -23990,18 +24019,18 @@ _tmp_140_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c> _tmp_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 52)) // token='...' ) { - D(fprintf(stderr, "%*c+ _tmp_140[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); + D(fprintf(stderr, "%*c+ _tmp_141[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_140[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_141[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'")); } _res = NULL; @@ -24010,9 +24039,9 @@ _tmp_140_rule(Parser *p) return _res; } -// _tmp_141: '@' named_expression NEWLINE +// _tmp_142: '@' named_expression NEWLINE static void * -_tmp_141_rule(Parser *p) +_tmp_142_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -24026,7 +24055,7 @@ _tmp_141_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); + D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); Token * _literal; expr_ty f; Token * newline_var; @@ -24038,7 +24067,7 @@ _tmp_141_rule(Parser *p) (newline_var = _PyPegen_expect_token(p, NEWLINE)) // token='NEWLINE' ) { - D(fprintf(stderr, "%*c+ _tmp_141[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); + D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE")); _res = f; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -24048,7 +24077,7 @@ _tmp_141_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_141[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'@' named_expression NEWLINE")); } _res = NULL; @@ -24057,9 +24086,9 @@ _tmp_141_rule(Parser *p) return _res; } -// _tmp_142: ',' star_expression +// _tmp_143: ',' star_expression static void * -_tmp_142_rule(Parser *p) +_tmp_143_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -24073,7 +24102,7 @@ _tmp_142_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression")); + D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression")); Token * _literal; expr_ty c; if ( @@ -24082,7 +24111,7 @@ _tmp_142_rule(Parser *p) (c = star_expression_rule(p)) // star_expression ) { - D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression")); + D(fprintf(stderr, "%*c+ _tmp_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -24092,7 +24121,7 @@ _tmp_142_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_143[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_expression")); } _res = NULL; @@ -24101,9 +24130,9 @@ _tmp_142_rule(Parser *p) return _res; } -// _tmp_143: ',' expression +// _tmp_144: ',' expression static void * -_tmp_143_rule(Parser *p) +_tmp_144_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -24117,7 +24146,7 @@ _tmp_143_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression")); Token * _literal; expr_ty c; if ( @@ -24126,7 +24155,7 @@ _tmp_143_rule(Parser *p) (c = expression_rule(p)) // expression ) { - D(fprintf(stderr, "%*c+ _tmp_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression")); + D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -24136,7 +24165,7 @@ _tmp_143_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_143[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression")); } _res = NULL; @@ -24145,9 +24174,9 @@ _tmp_143_rule(Parser *p) return _res; } -// _tmp_144: 'or' conjunction +// _tmp_145: 'or' conjunction static void * -_tmp_144_rule(Parser *p) +_tmp_145_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -24161,7 +24190,7 @@ _tmp_144_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); + D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); Token * _keyword; expr_ty c; if ( @@ -24170,7 +24199,7 @@ _tmp_144_rule(Parser *p) (c = conjunction_rule(p)) // conjunction ) { - D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); + D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -24180,7 +24209,7 @@ _tmp_144_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'or' conjunction")); } _res = NULL; @@ -24189,9 +24218,9 @@ _tmp_144_rule(Parser *p) return _res; } -// _tmp_145: 'and' inversion +// _tmp_146: 'and' inversion static void * -_tmp_145_rule(Parser *p) +_tmp_146_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -24205,7 +24234,7 @@ _tmp_145_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion")); + D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion")); Token * _keyword; expr_ty c; if ( @@ -24214,7 +24243,7 @@ _tmp_145_rule(Parser *p) (c = inversion_rule(p)) // inversion ) { - D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion")); + D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -24224,7 +24253,7 @@ _tmp_145_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'and' inversion")); } _res = NULL; @@ -24233,9 +24262,9 @@ _tmp_145_rule(Parser *p) return _res; } -// _tmp_146: 'if' disjunction +// _tmp_147: 'if' disjunction static void * -_tmp_146_rule(Parser *p) +_tmp_147_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -24249,7 +24278,7 @@ _tmp_146_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); Token * _keyword; expr_ty z; if ( @@ -24258,7 +24287,7 @@ _tmp_146_rule(Parser *p) (z = disjunction_rule(p)) // disjunction ) { - D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -24268,7 +24297,7 @@ _tmp_146_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction")); } _res = NULL; @@ -24277,9 +24306,9 @@ _tmp_146_rule(Parser *p) return _res; } -// _tmp_147: 'if' disjunction +// _tmp_148: 'if' disjunction static void * -_tmp_147_rule(Parser *p) +_tmp_148_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -24293,7 +24322,7 @@ _tmp_147_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); Token * _keyword; expr_ty z; if ( @@ -24302,7 +24331,7 @@ _tmp_147_rule(Parser *p) (z = disjunction_rule(p)) // disjunction ) { - D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); + D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction")); _res = z; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -24312,7 +24341,7 @@ _tmp_147_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction")); } _res = NULL; @@ -24321,9 +24350,66 @@ _tmp_147_rule(Parser *p) return _res; } -// _tmp_148: ',' star_target +// _tmp_149: starred_expression | named_expression !'=' static void * -_tmp_148_rule(Parser *p) +_tmp_149_rule(Parser *p) +{ + D(p->level++); + if (p->error_indicator) { + D(p->level--); + return NULL; + } + void * _res = NULL; + int _mark = p->mark; + { // starred_expression + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression")); + expr_ty starred_expression_var; + if ( + (starred_expression_var = starred_expression_rule(p)) // starred_expression + ) + { + D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression")); + _res = starred_expression_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_149[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression")); + } + { // named_expression !'=' + if (p->error_indicator) { + D(p->level--); + return NULL; + } + D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression !'='")); + expr_ty named_expression_var; + if ( + (named_expression_var = named_expression_rule(p)) // named_expression + && + _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22) // token='=' + ) + { + D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "named_expression !'='")); + _res = named_expression_var; + goto done; + } + p->mark = _mark; + D(fprintf(stderr, "%*c%s _tmp_149[%d-%d]: %s failed!\n", p->level, ' ', + p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "named_expression !'='")); + } + _res = NULL; + done: + D(p->level--); + return _res; +} + +// _tmp_150: ',' star_target +static void * +_tmp_150_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -24337,7 +24423,7 @@ _tmp_148_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c> _tmp_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target")); Token * _literal; expr_ty c; if ( @@ -24346,7 +24432,7 @@ _tmp_148_rule(Parser *p) (c = star_target_rule(p)) // star_target ) { - D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); + D(fprintf(stderr, "%*c+ _tmp_150[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target")); _res = c; if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; @@ -24356,7 +24442,7 @@ _tmp_148_rule(Parser *p) goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_150[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target")); } _res = NULL; @@ -24365,9 +24451,9 @@ _tmp_148_rule(Parser *p) return _res; } -// _tmp_149: star_targets '=' +// _tmp_151: star_targets '=' static void * -_tmp_149_rule(Parser *p) +_tmp_151_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -24381,7 +24467,7 @@ _tmp_149_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty star_targets_var; if ( @@ -24390,12 +24476,12 @@ _tmp_149_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_151[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = _PyPegen_dummy_name(p, star_targets_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_149[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_151[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; @@ -24404,9 +24490,9 @@ _tmp_149_rule(Parser *p) return _res; } -// _tmp_150: star_targets '=' +// _tmp_152: star_targets '=' static void * -_tmp_150_rule(Parser *p) +_tmp_152_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -24420,7 +24506,7 @@ _tmp_150_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='")); Token * _literal; expr_ty star_targets_var; if ( @@ -24429,12 +24515,12 @@ _tmp_150_rule(Parser *p) (_literal = _PyPegen_expect_token(p, 22)) // token='=' ) { - D(fprintf(stderr, "%*c+ _tmp_150[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); + D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='")); _res = _PyPegen_dummy_name(p, star_targets_var, _literal); goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_150[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='")); } _res = NULL; @@ -24443,9 +24529,9 @@ _tmp_150_rule(Parser *p) return _res; } -// _loop1_151: param_with_default +// _loop1_153: param_with_default static asdl_seq * -_loop1_151_rule(Parser *p) +_loop1_153_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -24469,7 +24555,7 @@ _loop1_151_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop1_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); + D(fprintf(stderr, "%*c> _loop1_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default")); NameDefaultPair* param_with_default_var; while ( (param_with_default_var = param_with_default_rule(p)) // param_with_default @@ -24491,7 +24577,7 @@ _loop1_151_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_151[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_153[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -24509,14 +24595,14 @@ _loop1_151_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_151_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop1_153_type, _seq); D(p->level--); return _seq; } -// _loop1_152: lambda_param_with_default +// _loop1_154: lambda_param_with_default static asdl_seq * -_loop1_152_rule(Parser *p) +_loop1_154_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -24540,7 +24626,7 @@ _loop1_152_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _loop1_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); + D(fprintf(stderr, "%*c> _loop1_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default")); NameDefaultPair* lambda_param_with_default_var; while ( (lambda_param_with_default_var = lambda_param_with_default_rule(p)) // lambda_param_with_default @@ -24562,7 +24648,7 @@ _loop1_152_rule(Parser *p) _mark = p->mark; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _loop1_152[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _loop1_154[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default")); } if (_n == 0 || p->error_indicator) { @@ -24580,14 +24666,14 @@ _loop1_152_rule(Parser *p) } for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]); PyMem_Free(_children); - _PyPegen_insert_memo(p, _start_mark, _loop1_152_type, _seq); + _PyPegen_insert_memo(p, _start_mark, _loop1_154_type, _seq); D(p->level--); return _seq; } -// _tmp_153: ')' | '**' +// _tmp_155: ')' | '**' static void * -_tmp_153_rule(Parser *p) +_tmp_155_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -24601,18 +24687,18 @@ _tmp_153_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 8)) // token=')' ) { - D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); + D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'")); } { // '**' @@ -24620,18 +24706,18 @@ _tmp_153_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } _res = NULL; @@ -24640,9 +24726,9 @@ _tmp_153_rule(Parser *p) return _res; } -// _tmp_154: ':' | '**' +// _tmp_156: ':' | '**' static void * -_tmp_154_rule(Parser *p) +_tmp_156_rule(Parser *p) { D(p->level++); if (p->error_indicator) { @@ -24656,18 +24742,18 @@ _tmp_154_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c> _tmp_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 11)) // token=':' ) { - D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); + D(fprintf(stderr, "%*c+ _tmp_156[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_156[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'")); } { // '**' @@ -24675,18 +24761,18 @@ _tmp_154_rule(Parser *p) D(p->level--); return NULL; } - D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c> _tmp_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'")); Token * _literal; if ( (_literal = _PyPegen_expect_token(p, 35)) // token='**' ) { - D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); + D(fprintf(stderr, "%*c+ _tmp_156[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'")); _res = _literal; goto done; } p->mark = _mark; - D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ', + D(fprintf(stderr, "%*c%s _tmp_156[%d-%d]: %s failed!\n", p->level, ' ', p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'")); } _res = NULL; diff --git a/Parser/pegen.c b/Parser/pegen.c index f615907f5f571f..2507bc4b38280b 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -2217,3 +2217,38 @@ _PyPegen_nonparen_genexp_in_call(Parser *p, expr_ty args) "Generator expression must be parenthesized" ); } + + +expr_ty _PyPegen_collect_call_seqs(Parser *p, asdl_seq *a, asdl_seq *b) { + Py_ssize_t args_len = asdl_seq_LEN(a); + Py_ssize_t total_len = args_len; + + if (b == NULL) { + expr_ty first = asdl_seq_GET(a, 0); + expr_ty last = asdl_seq_GET(a, args_len - 1); + return _Py_Call(_PyPegen_dummy_name(p), a, NULL, EXTRA_EXPR(first, last)); + + } + + asdl_seq *starreds = _PyPegen_seq_extract_starred_exprs(p, b); + asdl_seq *keywords = _PyPegen_seq_delete_starred_exprs(p, b); + + if (starreds) { + total_len += asdl_seq_LEN(starreds); + } + + asdl_seq *args = _Py_asdl_seq_new(total_len, p->arena); + + Py_ssize_t i = 0; + for (i = 0; i < args_len; i++) { + asdl_seq_SET(args, i, asdl_seq_GET(a, i)); + } + for (; i < total_len; i++) { + asdl_seq_SET(args, i, asdl_seq_GET(starreds, i - args_len)); + } + + expr_ty first = asdl_seq_GET(args, 0); + expr_ty last = asdl_seq_GET(b, asdl_seq_LEN(b)-1); + + return _Py_Call(_PyPegen_dummy_name(p), args, keywords, EXTRA_EXPR(first, last)); +} diff --git a/Parser/pegen.h b/Parser/pegen.h index f407709863c69e..3e74e3ac73e0a3 100644 --- a/Parser/pegen.h +++ b/Parser/pegen.h @@ -257,6 +257,7 @@ stmt_ty _PyPegen_class_def_decorators(Parser *, asdl_seq *, stmt_ty); KeywordOrStarred *_PyPegen_keyword_or_starred(Parser *, void *, int); asdl_seq *_PyPegen_seq_extract_starred_exprs(Parser *, asdl_seq *); asdl_seq *_PyPegen_seq_delete_starred_exprs(Parser *, asdl_seq *); +expr_ty _PyPegen_collect_call_seqs(Parser *, asdl_seq *, asdl_seq *); expr_ty _PyPegen_concatenate_strings(Parser *p, asdl_seq *); asdl_seq *_PyPegen_join_sequences(Parser *, asdl_seq *, asdl_seq *); int _PyPegen_check_barry_as_flufl(Parser *); From 0770ad948cb6d9f7f6c4002efd83e27c27069808 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Wed, 2 Sep 2020 21:54:46 -0700 Subject: [PATCH 49/63] bpo-41696: Fix handling of debug mode in asyncio.run (#22069) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * bpo-41696: Fix handling of debug mode in asyncio.run This allows PYTHONASYNCIODEBUG or -X dev to enable asyncio debug mode when using asyncio.run * 📜🤖 Added by blurb_it. Co-authored-by: hauntsaninja <> Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> --- Lib/asyncio/runners.py | 5 +++-- Lib/test/test_asyncio/test_runners.py | 3 +++ .../next/Library/2020-09-03-01-35-32.bpo-41696.zkYGre.rst | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2020-09-03-01-35-32.bpo-41696.zkYGre.rst diff --git a/Lib/asyncio/runners.py b/Lib/asyncio/runners.py index 03ce33300eba83..268635d68fb0c0 100644 --- a/Lib/asyncio/runners.py +++ b/Lib/asyncio/runners.py @@ -5,7 +5,7 @@ from . import tasks -def run(main, *, debug=False): +def run(main, *, debug=None): """Execute the coroutine and return the result. This function runs the passed coroutine, taking care of @@ -39,7 +39,8 @@ async def main(): loop = events.new_event_loop() try: events.set_event_loop(loop) - loop.set_debug(debug) + if debug is not None: + loop.set_debug(debug) return loop.run_until_complete(main) finally: try: diff --git a/Lib/test/test_asyncio/test_runners.py b/Lib/test/test_asyncio/test_runners.py index 3b58ddee443adf..b9ae02dc3c04e0 100644 --- a/Lib/test/test_asyncio/test_runners.py +++ b/Lib/test/test_asyncio/test_runners.py @@ -87,6 +87,9 @@ async def main(expected): asyncio.run(main(False)) asyncio.run(main(True), debug=True) + with mock.patch('asyncio.coroutines._is_debug_mode', lambda: True): + asyncio.run(main(True)) + asyncio.run(main(False), debug=False) def test_asyncio_run_from_running_loop(self): async def main(): diff --git a/Misc/NEWS.d/next/Library/2020-09-03-01-35-32.bpo-41696.zkYGre.rst b/Misc/NEWS.d/next/Library/2020-09-03-01-35-32.bpo-41696.zkYGre.rst new file mode 100644 index 00000000000000..67bbbb857f18cb --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-09-03-01-35-32.bpo-41696.zkYGre.rst @@ -0,0 +1 @@ +Fix handling of debug mode in :func:`asyncio.run`. This allows setting ``PYTHONASYNCIODEBUG`` or ``-X dev`` to enable asyncio debug mode when using :func:`asyncio.run`. \ No newline at end of file From be435ae2b064dc64f04475bec632862e1dbf605f Mon Sep 17 00:00:00 2001 From: Ben Darnell Date: Thu, 3 Sep 2020 00:58:50 -0400 Subject: [PATCH 50/63] bpo-39010: Improve test shutdown (#22066) Simply closing the event loop isn't enough to avoid warnings. If we don't also shut down the event loop's default executor, it sometimes logs a "dangling thread" warning. Follow-up to GH-22017 --- Lib/test/test_asyncio/test_windows_events.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_asyncio/test_windows_events.py b/Lib/test/test_asyncio/test_windows_events.py index 33388a87d48f3f..f276cd205a2f8e 100644 --- a/Lib/test/test_asyncio/test_windows_events.py +++ b/Lib/test/test_asyncio/test_windows_events.py @@ -225,10 +225,18 @@ def test_read_self_pipe_restart(self): self.loop.run_forever() self.loop.stop() self.loop.run_forever() - # If we don't wait for f to complete here, we may get another - # warning logged about a thread that didn't shut down cleanly. + + # Shut everything down cleanly. This is an important part of the + # test - in issue 39010, the error occurred during loop.close(), + # so we want to close the loop during the test instead of leaving + # it for tearDown. + # + # First wait for f to complete to avoid a "future's result was never + # retrieved" error. self.loop.run_until_complete(f) - self.loop.close() + # Now shut down the loop itself (self.close_loop also shuts down the + # loop's default executor). + self.close_loop(self.loop) self.assertFalse(self.loop.call_exception_handler.called) From e223d06a8b2067c68e9f97c4628c2b0f056dcae6 Mon Sep 17 00:00:00 2001 From: Todd Date: Thu, 3 Sep 2020 01:22:36 -0400 Subject: [PATCH 51/63] bpo-39883: Use BSD0 license for code in docs (GH-17635) The PSF board approved this use. --- Doc/license.rst | 34 +++++++++++++++++++ LICENSE | 25 ++++++++++++++ .../2020-03-07-03-53-39.bpo-39883.1tnb4-.rst | 1 + 3 files changed, 60 insertions(+) create mode 100644 Misc/NEWS.d/next/Documentation/2020-03-07-03-53-39.bpo-39883.1tnb4-.rst diff --git a/Doc/license.rst b/Doc/license.rst index fa6d71a78042d1..4030825bbd28ee 100644 --- a/Doc/license.rst +++ b/Doc/license.rst @@ -72,6 +72,19 @@ make these releases possible. Terms and conditions for accessing or otherwise using Python ============================================================ +Python software and documentation are licensed under the +:ref:`PSF License Agreement `. + +Starting with Python 3.8.6, examples, recipes, and other code in +the documentation are dual licensed under the PSF License Agreement +and the :ref:`Zero-Clause BSD license `. + +Some software incorporated into Python is under different licenses. +The licenses are listed with code falling under that license. +See :ref:`OtherLicenses` for an incomplete list of these licenses. + + +.. _PSF-license: PSF LICENSE AGREEMENT FOR PYTHON |release| ------------------------------------------ @@ -258,6 +271,27 @@ CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 SOFTWARE. +.. _BSD0: + +ZERO-CLAUSE BSD LICENSE FOR CODE IN THE PYTHON |release| DOCUMENTATION +---------------------------------------------------------------------- + +.. parsed-literal:: + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + PERFORMANCE OF THIS SOFTWARE. + + +.. _OtherLicenses: + Licenses and Acknowledgements for Incorporated Software ======================================================= diff --git a/LICENSE b/LICENSE index 66a3ac80d729a3..f42f8adbed845d 100644 --- a/LICENSE +++ b/LICENSE @@ -59,6 +59,17 @@ direction to make these releases possible. B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON =============================================================== +Python software and documentation are licensed under the +Python Software Foundation License Version 2. + +Starting with Python 3.8.6, examples, recipes, and other code in +the documentation are dual licensed under the PSF License Version 2 +and the Zero-Clause BSD license. + +Some software incorporated into Python is under different licenses. +The licenses are listed with code falling under that license. + + PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 -------------------------------------------- @@ -252,3 +263,17 @@ FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +ZERO-CLAUSE BSD LICENSE FOR CODE IN THE PYTHON DOCUMENTATION +---------------------------------------------------------------------- + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. diff --git a/Misc/NEWS.d/next/Documentation/2020-03-07-03-53-39.bpo-39883.1tnb4-.rst b/Misc/NEWS.d/next/Documentation/2020-03-07-03-53-39.bpo-39883.1tnb4-.rst new file mode 100644 index 00000000000000..4941d50a560e2e --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2020-03-07-03-53-39.bpo-39883.1tnb4-.rst @@ -0,0 +1 @@ +Make code, examples, and recipes in the Python documentation be licensed under the more permissive BSD0 license in addition to the existing Python 2.0 license. \ No newline at end of file From 71d1bd9569c8a497e279f2fea6fe47cd70a87ea3 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Thu, 3 Sep 2020 03:21:06 -0500 Subject: [PATCH 52/63] bpo-1635741: Port _signal module to multi-phase init (PEP 489) (GH-22049) --- ...2020-09-01-17-07-20.bpo-1635741.7wSuCc.rst | 1 + Modules/signalmodule.c | 168 +++++++++--------- 2 files changed, 87 insertions(+), 82 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2020-09-01-17-07-20.bpo-1635741.7wSuCc.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-09-01-17-07-20.bpo-1635741.7wSuCc.rst b/Misc/NEWS.d/next/Core and Builtins/2020-09-01-17-07-20.bpo-1635741.7wSuCc.rst new file mode 100644 index 00000000000000..ff7cb352869a22 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-09-01-17-07-20.bpo-1635741.7wSuCc.rst @@ -0,0 +1 @@ +Port the :mod:`_signal` extension module to multi-phase initialization (:pep:`489`). diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index c49a3ea52e71de..262f2b66a57e29 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -1377,77 +1377,63 @@ ITIMER_PROF -- decrements both when the process is executing and\n\ A signal handler function is called with two arguments:\n\ the first is the signal number, the second is the interrupted stack frame."); -static struct PyModuleDef signalmodule = { - PyModuleDef_HEAD_INIT, - "_signal", - module_doc, - -1, - signal_methods, - NULL, - NULL, - NULL, - NULL -}; - -PyMODINIT_FUNC -PyInit__signal(void) -{ - PyObject *m, *d; - int i; - /* Create the module and add the functions */ - m = PyModule_Create(&signalmodule); - if (m == NULL) - return NULL; +static int +signal_exec(PyObject *m) +{ + /* add the functions */ #if defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT) if (!initialized) { - if (PyStructSequence_InitType2(&SiginfoType, &struct_siginfo_desc) < 0) - return NULL; + if (PyStructSequence_InitType2(&SiginfoType, &struct_siginfo_desc) < 0) { + return -1; + } + } + + if (PyModule_AddType(m, &SiginfoType) < 0) { + return -1; } - Py_INCREF((PyObject*) &SiginfoType); - PyModule_AddObject(m, "struct_siginfo", (PyObject*) &SiginfoType); initialized = 1; #endif /* Add some symbolic constants to the module */ - d = PyModule_GetDict(m); + PyObject *d = PyModule_GetDict(m); DefaultHandler = PyLong_FromVoidPtr((void *)SIG_DFL); if (!DefaultHandler || PyDict_SetItemString(d, "SIG_DFL", DefaultHandler) < 0) { - goto finally; + return -1; } IgnoreHandler = PyLong_FromVoidPtr((void *)SIG_IGN); if (!IgnoreHandler || PyDict_SetItemString(d, "SIG_IGN", IgnoreHandler) < 0) { - goto finally; + return -1; } if (PyModule_AddIntMacro(m, NSIG)) - goto finally; + return -1; #ifdef SIG_BLOCK if (PyModule_AddIntMacro(m, SIG_BLOCK)) - goto finally; + return -1; #endif #ifdef SIG_UNBLOCK if (PyModule_AddIntMacro(m, SIG_UNBLOCK)) - goto finally; + return -1; #endif #ifdef SIG_SETMASK if (PyModule_AddIntMacro(m, SIG_SETMASK)) - goto finally; + return -1; #endif IntHandler = PyDict_GetItemString(d, "default_int_handler"); if (!IntHandler) - goto finally; + return -1; Py_INCREF(IntHandler); _Py_atomic_store_relaxed(&Handlers[0].tripped, 0); - for (i = 1; i < NSIG; i++) { + for (int i = 1; i < NSIG; i++) { void (*t)(int); t = PyOS_getsig(i); _Py_atomic_store_relaxed(&Handlers[i].tripped, 0); @@ -1468,168 +1454,168 @@ PyInit__signal(void) #ifdef SIGHUP if (PyModule_AddIntMacro(m, SIGHUP)) - goto finally; + return -1; #endif #ifdef SIGINT if (PyModule_AddIntMacro(m, SIGINT)) - goto finally; + return -1; #endif #ifdef SIGBREAK if (PyModule_AddIntMacro(m, SIGBREAK)) - goto finally; + return -1; #endif #ifdef SIGQUIT if (PyModule_AddIntMacro(m, SIGQUIT)) - goto finally; + return -1; #endif #ifdef SIGILL if (PyModule_AddIntMacro(m, SIGILL)) - goto finally; + return -1; #endif #ifdef SIGTRAP if (PyModule_AddIntMacro(m, SIGTRAP)) - goto finally; + return -1; #endif #ifdef SIGIOT if (PyModule_AddIntMacro(m, SIGIOT)) - goto finally; + return -1; #endif #ifdef SIGABRT if (PyModule_AddIntMacro(m, SIGABRT)) - goto finally; + return -1; #endif #ifdef SIGEMT if (PyModule_AddIntMacro(m, SIGEMT)) - goto finally; + return -1; #endif #ifdef SIGFPE if (PyModule_AddIntMacro(m, SIGFPE)) - goto finally; + return -1; #endif #ifdef SIGKILL if (PyModule_AddIntMacro(m, SIGKILL)) - goto finally; + return -1; #endif #ifdef SIGBUS if (PyModule_AddIntMacro(m, SIGBUS)) - goto finally; + return -1; #endif #ifdef SIGSEGV if (PyModule_AddIntMacro(m, SIGSEGV)) - goto finally; + return -1; #endif #ifdef SIGSYS if (PyModule_AddIntMacro(m, SIGSYS)) - goto finally; + return -1; #endif #ifdef SIGPIPE if (PyModule_AddIntMacro(m, SIGPIPE)) - goto finally; + return -1; #endif #ifdef SIGALRM if (PyModule_AddIntMacro(m, SIGALRM)) - goto finally; + return -1; #endif #ifdef SIGTERM if (PyModule_AddIntMacro(m, SIGTERM)) - goto finally; + return -1; #endif #ifdef SIGUSR1 if (PyModule_AddIntMacro(m, SIGUSR1)) - goto finally; + return -1; #endif #ifdef SIGUSR2 if (PyModule_AddIntMacro(m, SIGUSR2)) - goto finally; + return -1; #endif #ifdef SIGCLD if (PyModule_AddIntMacro(m, SIGCLD)) - goto finally; + return -1; #endif #ifdef SIGCHLD if (PyModule_AddIntMacro(m, SIGCHLD)) - goto finally; + return -1; #endif #ifdef SIGPWR if (PyModule_AddIntMacro(m, SIGPWR)) - goto finally; + return -1; #endif #ifdef SIGIO if (PyModule_AddIntMacro(m, SIGIO)) - goto finally; + return -1; #endif #ifdef SIGURG if (PyModule_AddIntMacro(m, SIGURG)) - goto finally; + return -1; #endif #ifdef SIGWINCH if (PyModule_AddIntMacro(m, SIGWINCH)) - goto finally; + return -1; #endif #ifdef SIGPOLL if (PyModule_AddIntMacro(m, SIGPOLL)) - goto finally; + return -1; #endif #ifdef SIGSTOP if (PyModule_AddIntMacro(m, SIGSTOP)) - goto finally; + return -1; #endif #ifdef SIGTSTP if (PyModule_AddIntMacro(m, SIGTSTP)) - goto finally; + return -1; #endif #ifdef SIGCONT if (PyModule_AddIntMacro(m, SIGCONT)) - goto finally; + return -1; #endif #ifdef SIGTTIN if (PyModule_AddIntMacro(m, SIGTTIN)) - goto finally; + return -1; #endif #ifdef SIGTTOU if (PyModule_AddIntMacro(m, SIGTTOU)) - goto finally; + return -1; #endif #ifdef SIGVTALRM if (PyModule_AddIntMacro(m, SIGVTALRM)) - goto finally; + return -1; #endif #ifdef SIGPROF if (PyModule_AddIntMacro(m, SIGPROF)) - goto finally; + return -1; #endif #ifdef SIGXCPU if (PyModule_AddIntMacro(m, SIGXCPU)) - goto finally; + return -1; #endif #ifdef SIGXFSZ if (PyModule_AddIntMacro(m, SIGXFSZ)) - goto finally; + return -1; #endif #ifdef SIGRTMIN if (PyModule_AddIntMacro(m, SIGRTMIN)) - goto finally; + return -1; #endif #ifdef SIGRTMAX if (PyModule_AddIntMacro(m, SIGRTMAX)) - goto finally; + return -1; #endif #ifdef SIGINFO if (PyModule_AddIntMacro(m, SIGINFO)) - goto finally; + return -1; #endif #ifdef ITIMER_REAL if (PyModule_AddIntMacro(m, ITIMER_REAL)) - goto finally; + return -1; #endif #ifdef ITIMER_VIRTUAL if (PyModule_AddIntMacro(m, ITIMER_VIRTUAL)) - goto finally; + return -1; #endif #ifdef ITIMER_PROF if (PyModule_AddIntMacro(m, ITIMER_PROF)) - goto finally; + return -1; #endif #if defined (HAVE_SETITIMER) || defined (HAVE_GETITIMER) @@ -1637,18 +1623,18 @@ PyInit__signal(void) PyExc_OSError, NULL); if (!ItimerError || PyDict_SetItemString(d, "ItimerError", ItimerError) < 0) { - goto finally; + return -1; } #endif #ifdef CTRL_C_EVENT if (PyModule_AddIntMacro(m, CTRL_C_EVENT)) - goto finally; + return -1; #endif #ifdef CTRL_BREAK_EVENT if (PyModule_AddIntMacro(m, CTRL_BREAK_EVENT)) - goto finally; + return -1; #endif #ifdef MS_WINDOWS @@ -1657,12 +1643,30 @@ PyInit__signal(void) #endif if (PyErr_Occurred()) { - Py_DECREF(m); - m = NULL; + return -1; } - finally: - return m; + return 0; +} + +static PyModuleDef_Slot signal_slots[] = { + {Py_mod_exec, signal_exec}, + {0, NULL} +}; + +static struct PyModuleDef signalmodule = { + PyModuleDef_HEAD_INIT, + "_signal", + .m_doc = module_doc, + .m_size = 0, + .m_methods = signal_methods, + .m_slots = signal_slots +}; + +PyMODINIT_FUNC +PyInit__signal(void) +{ + return PyModuleDef_Init(&signalmodule); } static void From 851606007665dc30089e5e1953208c5428e455b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20=C5=A0a=C5=A1ko?= Date: Thu, 3 Sep 2020 12:00:10 +0200 Subject: [PATCH 53/63] [doc] Fix a typo in the graphlib docs (#22030) --- Doc/library/graphlib.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/graphlib.rst b/Doc/library/graphlib.rst index 820615e7230157..0faca2186b268c 100644 --- a/Doc/library/graphlib.rst +++ b/Doc/library/graphlib.rst @@ -121,7 +121,7 @@ if ts.is_active(): ... - if possible to simply do:: + it is possible to simply do:: if ts: ... From 315a61f7a9418d904e0eea14b1f054fac3a90e9f Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Thu, 3 Sep 2020 15:29:32 +0100 Subject: [PATCH 54/63] bpo-41697: Correctly handle KeywordOrStarred when parsing arguments in the parser (GH-22077) --- Grammar/python.gram | 2 +- Parser/parser.c | 11 ++++++++++- Parser/pegen.c | 17 +++++++++-------- Parser/pegen.h | 4 +++- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/Grammar/python.gram b/Grammar/python.gram index 84835b731c540f..524e88eb389968 100644 --- a/Grammar/python.gram +++ b/Grammar/python.gram @@ -535,7 +535,7 @@ arguments[expr_ty] (memo): | a=args [','] &')' { a } | incorrect_arguments args[expr_ty]: - | a=','.(starred_expression | named_expression !'=')+ b=[',' k=kwargs {k}] { _PyPegen_collect_call_seqs(p, a, b) } + | a=','.(starred_expression | named_expression !'=')+ b=[',' k=kwargs {k}] { _PyPegen_collect_call_seqs(p, a, b, EXTRA) } | a=kwargs { _Py_Call(_PyPegen_dummy_name(p), CHECK_NULL_ALLOWED(_PyPegen_seq_extract_starred_exprs(p, a)), CHECK_NULL_ALLOWED(_PyPegen_seq_delete_starred_exprs(p, a)), diff --git a/Parser/parser.c b/Parser/parser.c index 3e724a260d90a9..8a7cb62fd7cf8d 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -12237,7 +12237,16 @@ args_rule(Parser *p) ) { D(fprintf(stderr, "%*c+ args[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.(starred_expression | named_expression !'=')+ [',' kwargs]")); - _res = _PyPegen_collect_call_seqs ( p , a , b ); + Token *_token = _PyPegen_get_last_nonnwhitespace_token(p); + if (_token == NULL) { + D(p->level--); + return NULL; + } + int _end_lineno = _token->end_lineno; + UNUSED(_end_lineno); // Only used by EXTRA macro + int _end_col_offset = _token->end_col_offset; + UNUSED(_end_col_offset); // Only used by EXTRA macro + _res = _PyPegen_collect_call_seqs ( p , a , b , EXTRA ); if (_res == NULL && PyErr_Occurred()) { p->error_indicator = 1; D(p->level--); diff --git a/Parser/pegen.c b/Parser/pegen.c index 2507bc4b38280b..4beb2abdd296aa 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -2219,14 +2219,15 @@ _PyPegen_nonparen_genexp_in_call(Parser *p, expr_ty args) } -expr_ty _PyPegen_collect_call_seqs(Parser *p, asdl_seq *a, asdl_seq *b) { +expr_ty _PyPegen_collect_call_seqs(Parser *p, asdl_seq *a, asdl_seq *b, + int lineno, int col_offset, int end_lineno, + int end_col_offset, PyArena *arena) { Py_ssize_t args_len = asdl_seq_LEN(a); Py_ssize_t total_len = args_len; if (b == NULL) { - expr_ty first = asdl_seq_GET(a, 0); - expr_ty last = asdl_seq_GET(a, args_len - 1); - return _Py_Call(_PyPegen_dummy_name(p), a, NULL, EXTRA_EXPR(first, last)); + return _Py_Call(_PyPegen_dummy_name(p), a, NULL, lineno, col_offset, + end_lineno, end_col_offset, arena); } @@ -2237,7 +2238,7 @@ expr_ty _PyPegen_collect_call_seqs(Parser *p, asdl_seq *a, asdl_seq *b) { total_len += asdl_seq_LEN(starreds); } - asdl_seq *args = _Py_asdl_seq_new(total_len, p->arena); + asdl_seq *args = _Py_asdl_seq_new(total_len, arena); Py_ssize_t i = 0; for (i = 0; i < args_len; i++) { @@ -2247,8 +2248,8 @@ expr_ty _PyPegen_collect_call_seqs(Parser *p, asdl_seq *a, asdl_seq *b) { asdl_seq_SET(args, i, asdl_seq_GET(starreds, i - args_len)); } - expr_ty first = asdl_seq_GET(args, 0); - expr_ty last = asdl_seq_GET(b, asdl_seq_LEN(b)-1); + return _Py_Call(_PyPegen_dummy_name(p), args, keywords, lineno, + col_offset, end_lineno, end_col_offset, arena); + - return _Py_Call(_PyPegen_dummy_name(p), args, keywords, EXTRA_EXPR(first, last)); } diff --git a/Parser/pegen.h b/Parser/pegen.h index 3e74e3ac73e0a3..c81681efad2080 100644 --- a/Parser/pegen.h +++ b/Parser/pegen.h @@ -257,7 +257,9 @@ stmt_ty _PyPegen_class_def_decorators(Parser *, asdl_seq *, stmt_ty); KeywordOrStarred *_PyPegen_keyword_or_starred(Parser *, void *, int); asdl_seq *_PyPegen_seq_extract_starred_exprs(Parser *, asdl_seq *); asdl_seq *_PyPegen_seq_delete_starred_exprs(Parser *, asdl_seq *); -expr_ty _PyPegen_collect_call_seqs(Parser *, asdl_seq *, asdl_seq *); +expr_ty _PyPegen_collect_call_seqs(Parser *, asdl_seq *, asdl_seq *, + int lineno, int col_offset, int end_lineno, + int end_col_offset, PyArena *arena); expr_ty _PyPegen_concatenate_strings(Parser *p, asdl_seq *); asdl_seq *_PyPegen_join_sequences(Parser *, asdl_seq *, asdl_seq *); int _PyPegen_check_barry_as_flufl(Parser *); From e55a0e971b4bf9e6473bf0ca6bebdff76c075ef6 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Thu, 3 Sep 2020 15:29:55 +0100 Subject: [PATCH 55/63] Fix 'gather' rules in the python parser generator (GH-22021) Currently, empty sequences in gather rules make the conditional for gather rules fail as empty sequences evaluate as "False". We need to explicitly check for "None" (the failure condition) to avoid false negatives. --- Lib/test/test_peg_generator/test_pegen.py | 16 +++++++++++++++- Tools/peg_generator/pegen/python_generator.py | 3 +++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_peg_generator/test_pegen.py b/Lib/test/test_peg_generator/test_pegen.py index 5b4e964d698ade..bcfee3f2c5f8c3 100644 --- a/Lib/test/test_peg_generator/test_pegen.py +++ b/Lib/test/test_peg_generator/test_pegen.py @@ -74,7 +74,7 @@ def test_typed_rules(self) -> None: "Rule('term', 'int', Rhs([Alt([NamedItem(None, NameLeaf('NUMBER'))])]))" ) - def test_repeat_with_separator_rules(self) -> None: + def test_gather(self) -> None: grammar = """ start: ','.thing+ NEWLINE thing: NUMBER @@ -85,6 +85,20 @@ def test_repeat_with_separator_rules(self) -> None: "Rule('start', None, Rhs([Alt([NamedItem(None, Gather(StringLeaf(\"','\"), NameLeaf('thing'" )) self.assertEqual(str(rules["thing"]), "thing: NUMBER") + parser_class = make_parser(grammar) + node = parse_string("42\n", parser_class) + assert node == [ + [[TokenInfo(NUMBER, string="42", start=(1, 0), end=(1, 2), line="42\n")]], + TokenInfo(NEWLINE, string="\n", start=(1, 2), end=(1, 3), line="42\n"), + ] + node = parse_string("1, 2\n", parser_class) + assert node == [ + [ + [TokenInfo(NUMBER, string="1", start=(1, 0), end=(1, 1), line="1, 2\n")], + [TokenInfo(NUMBER, string="2", start=(1, 3), end=(1, 4), line="1, 2\n")], + ], + TokenInfo(NEWLINE, string="\n", start=(1, 4), end=(1, 5), line="1, 2\n"), + ] def test_expr_grammar(self) -> None: grammar = """ diff --git a/Tools/peg_generator/pegen/python_generator.py b/Tools/peg_generator/pegen/python_generator.py index 45a75975dbf5e0..b786de7fee5b43 100644 --- a/Tools/peg_generator/pegen/python_generator.py +++ b/Tools/peg_generator/pegen/python_generator.py @@ -217,6 +217,9 @@ def visit_Alt(self, node: Alt, is_loop: bool, is_gather: bool) -> None: else: self.print("and") self.visit(item) + if is_gather: + self.print("is not None") + self.print("):") with self.indent(): action = node.action From cdbff3527c5b10e79761ad25316b46cd079304bc Mon Sep 17 00:00:00 2001 From: Vinay Sajip Date: Thu, 3 Sep 2020 19:44:12 +0100 Subject: [PATCH 56/63] [doc] Update documentation on logging optimization. (GH-22075) --- Doc/howto/logging.rst | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/Doc/howto/logging.rst b/Doc/howto/logging.rst index 6316e086ef43ba..b4dd9206c9d524 100644 --- a/Doc/howto/logging.rst +++ b/Doc/howto/logging.rst @@ -1078,20 +1078,22 @@ need more precise control over what logging information is collected. Here's a list of things you can do to avoid processing during logging which you don't need: -+-----------------------------------------------+----------------------------------------+ -| What you don't want to collect | How to avoid collecting it | -+===============================================+========================================+ -| Information about where calls were made from. | Set ``logging._srcfile`` to ``None``. | -| | This avoids calling | -| | :func:`sys._getframe`, which may help | -| | to speed up your code in environments | -| | like PyPy (which can't speed up code | -| | that uses :func:`sys._getframe`). | -+-----------------------------------------------+----------------------------------------+ -| Threading information. | Set ``logging.logThreads`` to ``0``. | -+-----------------------------------------------+----------------------------------------+ -| Process information. | Set ``logging.logProcesses`` to ``0``. | -+-----------------------------------------------+----------------------------------------+ ++-----------------------------------------------------+---------------------------------------------------+ +| What you don't want to collect | How to avoid collecting it | ++=====================================================+===================================================+ +| Information about where calls were made from. | Set ``logging._srcfile`` to ``None``. | +| | This avoids calling :func:`sys._getframe`, which | +| | may help to speed up your code in environments | +| | like PyPy (which can't speed up code that uses | +| | :func:`sys._getframe`). | ++-----------------------------------------------------+---------------------------------------------------+ +| Threading information. | Set ``logging.logThreads`` to ``False``. | ++-----------------------------------------------------+---------------------------------------------------+ +| Current process ID (:func:`os.getpid`) | Set ``logging.logProcesses`` to ``False``. | ++-----------------------------------------------------+---------------------------------------------------+ +| Current process name when using ``multiprocessing`` | Set ``logging.logMultiprocessing`` to ``False``. | +| to manage multiple processes. | | ++-----------------------------------------------------+---------------------------------------------------+ Also note that the core logging module only includes the basic handlers. If you don't import :mod:`logging.handlers` and :mod:`logging.config`, they won't From 54a66ade2067c373d31003ad260e1b7d14c81564 Mon Sep 17 00:00:00 2001 From: Dong-hee Na Date: Fri, 4 Sep 2020 08:47:40 +0000 Subject: [PATCH 57/63] bpo-41700: Skip test if the locale is not supported (GH-22081) --- Lib/test/test_c_locale_coercion.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_c_locale_coercion.py b/Lib/test/test_c_locale_coercion.py index 8340a9eb2ea3a3..fcc85992345dbc 100644 --- a/Lib/test/test_c_locale_coercion.py +++ b/Lib/test/test_c_locale_coercion.py @@ -407,7 +407,10 @@ def test_PYTHONCOERCECLOCALE_set_to_one(self): # skip the test if the LC_CTYPE locale is C or coerced old_loc = locale.setlocale(locale.LC_CTYPE, None) self.addCleanup(locale.setlocale, locale.LC_CTYPE, old_loc) - loc = locale.setlocale(locale.LC_CTYPE, "") + try: + loc = locale.setlocale(locale.LC_CTYPE, "") + except locale.Error as e: + self.skipTest(str(e)) if loc == "C": self.skipTest("test requires LC_CTYPE locale different than C") if loc in TARGET_LOCALES : From 4b8032e5a4994a7902076efa72fca1e2c85d8b7f Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 4 Sep 2020 14:51:05 +0200 Subject: [PATCH 58/63] bpo-41713: _signal doesn't use multi-phase init (GH-22087) Partially revert commit 71d1bd9569c8a497e279f2fea6fe47cd70a87ea3: don't use multi-phase initialization (PEP 489) for the _signal extension module. --- ...2020-09-01-17-07-20.bpo-1635741.7wSuCc.rst | 1 - Modules/signalmodule.c | 20 ++++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2020-09-01-17-07-20.bpo-1635741.7wSuCc.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-09-01-17-07-20.bpo-1635741.7wSuCc.rst b/Misc/NEWS.d/next/Core and Builtins/2020-09-01-17-07-20.bpo-1635741.7wSuCc.rst deleted file mode 100644 index ff7cb352869a22..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2020-09-01-17-07-20.bpo-1635741.7wSuCc.rst +++ /dev/null @@ -1 +0,0 @@ -Port the :mod:`_signal` extension module to multi-phase initialization (:pep:`489`). diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index 262f2b66a57e29..3440894b2159d5 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -1649,26 +1649,32 @@ signal_exec(PyObject *m) return 0; } -static PyModuleDef_Slot signal_slots[] = { - {Py_mod_exec, signal_exec}, - {0, NULL} -}; static struct PyModuleDef signalmodule = { PyModuleDef_HEAD_INIT, "_signal", .m_doc = module_doc, - .m_size = 0, + .m_size = -1, .m_methods = signal_methods, - .m_slots = signal_slots }; + PyMODINIT_FUNC PyInit__signal(void) { - return PyModuleDef_Init(&signalmodule); + PyObject *mod = PyModule_Create(&signalmodule); + if (mod == NULL) { + return NULL; + } + + if (signal_exec(mod) < 0) { + Py_DECREF(mod); + return NULL; + } + return mod; } + static void finisignal(void) { From 81715808716198471fbca0a3db42ac408468dbc5 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Fri, 4 Sep 2020 20:55:41 +0300 Subject: [PATCH 59/63] bpo-41638: Improve ProgrammingError message for absent parameter. (GH-21999) It contains now the name of the parameter instead of its index when parameters are supplied as a dict. --- .../next/Library/2020-08-29-16-45-12.bpo-41638.iZfW5N.rst | 3 +++ Modules/_sqlite/statement.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2020-08-29-16-45-12.bpo-41638.iZfW5N.rst diff --git a/Misc/NEWS.d/next/Library/2020-08-29-16-45-12.bpo-41638.iZfW5N.rst b/Misc/NEWS.d/next/Library/2020-08-29-16-45-12.bpo-41638.iZfW5N.rst new file mode 100644 index 00000000000000..8ab7b5e9903dcb --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-08-29-16-45-12.bpo-41638.iZfW5N.rst @@ -0,0 +1,3 @@ +:exc:`~sqlite3.ProgrammingError` message for absent parameter in :mod:`sqlite3` +contains now the name of the parameter instead of its index when parameters +are supplied as a dict. diff --git a/Modules/_sqlite/statement.c b/Modules/_sqlite/statement.c index 9de8f9b67228f5..26599b423eb8b9 100644 --- a/Modules/_sqlite/statement.c +++ b/Modules/_sqlite/statement.c @@ -295,7 +295,7 @@ void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* para Py_DECREF(binding_name_obj); if (!current_param) { if (!PyErr_Occurred() || PyErr_ExceptionMatches(PyExc_LookupError)) { - PyErr_Format(pysqlite_ProgrammingError, "You did not supply a value for binding %d.", i); + PyErr_Format(pysqlite_ProgrammingError, "You did not supply a value for binding parameter :%s.", binding_name); } return; } From 306cfb3a37e1438f6ba9f0a9f3af3c00aae4ec64 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Fri, 4 Sep 2020 21:19:30 +0300 Subject: [PATCH 60/63] bpo-40486: Specify what happens if directory content change diring iteration (GH-22025) --- Doc/library/glob.rst | 4 +++- Doc/library/os.rst | 11 +++++++++-- Doc/library/pathlib.rst | 5 +++++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Doc/library/glob.rst b/Doc/library/glob.rst index 280e9f08266024..3fdba6937c1de0 100644 --- a/Doc/library/glob.rst +++ b/Doc/library/glob.rst @@ -43,7 +43,9 @@ For example, ``'[?]'`` matches the character ``'?'``. (like :file:`/usr/src/Python-1.5/Makefile`) or relative (like :file:`../../Tools/\*/\*.gif`), and can contain shell-style wildcards. Broken symlinks are included in the results (as in the shell). Whether or not the - results are sorted depends on the file system. + results are sorted depends on the file system. If a file that satisfies + conditions is removed or added during the call of this function, whether + a path name for that file be included is unspecified. If *root_dir* is not ``None``, it should be a :term:`path-like object` specifying the root directory for searching. It has the same effect on diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 275b2d390e7cf5..8c3bc5fb87d61b 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -1852,6 +1852,8 @@ features: Return a list containing the names of the entries in the directory given by *path*. The list is in arbitrary order, and does not include the special entries ``'.'`` and ``'..'`` even if they are present in the directory. + If a file is removed from or added to the directory during the call of + this function, whether a name for that file be included is unspecified. *path* may be a :term:`path-like object`. If *path* is of type ``bytes`` (directly or indirectly through the :class:`PathLike` interface), @@ -2257,7 +2259,9 @@ features: Return an iterator of :class:`os.DirEntry` objects corresponding to the entries in the directory given by *path*. The entries are yielded in arbitrary order, and the special entries ``'.'`` and ``'..'`` are not - included. + included. If a file is removed from or added to the directory after + creating the iterator, whether an entry for that file be included is + unspecified. Using :func:`scandir` instead of :func:`listdir` can significantly increase the performance of code that also needs file type or file @@ -3007,7 +3011,10 @@ features: *filenames* is a list of the names of the non-directory files in *dirpath*. Note that the names in the lists contain no path components. To get a full path (which begins with *top*) to a file or directory in *dirpath*, do - ``os.path.join(dirpath, name)``. + ``os.path.join(dirpath, name)``. Whether or not the lists are sorted + depends on the file system. If a file is removed from or added to the + *dirpath* directory during generating the lists, whether a name for that + file be included is unspecified. If optional argument *topdown* is ``True`` or not specified, the triple for a directory is generated before the triples for any of its subdirectories diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index 04810f5204397b..23486b625072f3 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -890,6 +890,11 @@ call fails (for example because the path doesn't exist). PosixPath('docs/_static') PosixPath('docs/Makefile') + The children are yielded in arbitrary order, and the special entries + ``'.'`` and ``'..'`` are not included. If a file is removed from or added + to the directory after creating the iterator, whether an path object for + that file be included is unspecified. + .. method:: Path.lchmod(mode) Like :meth:`Path.chmod` but, if the path points to a symbolic link, the From 84a7917b4c9afec07575065cffa143b91fe98c14 Mon Sep 17 00:00:00 2001 From: Stefan Krah Date: Fri, 4 Sep 2020 22:33:17 +0200 Subject: [PATCH 61/63] bpo-41721: Add xlc options (GH-22096) --- configure | 5 ++++- configure.ac | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 4c18ae7e364ca1..ad74754e9a7215 100755 --- a/configure +++ b/configure @@ -7592,11 +7592,14 @@ $as_echo "$MACOSX_DEPLOYMENT_TARGET" >&6; } ;; esac -# ICC needs -fp-model strict or floats behave badly case "$CC" in *icc*) + # ICC needs -fp-model strict or floats behave badly CFLAGS_NODIST="$CFLAGS_NODIST -fp-model strict" ;; +*xlc*) + CFLAGS_NODIST="$CFLAGS_NODIST -qalias=noansi -qmaxmem=-1" + ;; esac if test "$assertions" = 'true'; then diff --git a/configure.ac b/configure.ac index 3b40f39124dad5..f0bc8c625844b6 100644 --- a/configure.ac +++ b/configure.ac @@ -1993,11 +1993,14 @@ yes) ;; esac -# ICC needs -fp-model strict or floats behave badly case "$CC" in *icc*) + # ICC needs -fp-model strict or floats behave badly CFLAGS_NODIST="$CFLAGS_NODIST -fp-model strict" ;; +*xlc*) + CFLAGS_NODIST="$CFLAGS_NODIST -qalias=noansi -qmaxmem=-1" + ;; esac if test "$assertions" = 'true'; then From 51b84f8e96a441c498210f827c1297ee4973525f Mon Sep 17 00:00:00 2001 From: Zackery Spytz Date: Fri, 4 Sep 2020 14:57:48 -0600 Subject: [PATCH 62/63] bpo-38585: Remove references to defusedexpat (GH-22095) defusedexpat is not maintained. --- Doc/library/xml.rst | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/Doc/library/xml.rst b/Doc/library/xml.rst index fb86b6f5564d76..1981cab7cd438d 100644 --- a/Doc/library/xml.rst +++ b/Doc/library/xml.rst @@ -20,7 +20,7 @@ Python's interfaces for processing XML are grouped in the ``xml`` package. The XML modules are not secure against erroneous or maliciously constructed data. If you need to parse untrusted or unauthenticated data see the :ref:`xml-vulnerabilities` and - :ref:`defused-packages` sections. + :ref:`defusedxml-package` sections. It is important to note that modules in the :mod:`xml` package require that there be at least one SAX-compliant XML parser available. The Expat parser is @@ -113,9 +113,9 @@ decompression bomb The documentation for `defusedxml`_ on PyPI has further information about all known attack vectors with examples and references. -.. _defused-packages: +.. _defusedxml-package: -The :mod:`defusedxml` and :mod:`defusedexpat` Packages +The :mod:`defusedxml` Package ------------------------------------------------------ `defusedxml`_ is a pure Python package with modified subclasses of all stdlib @@ -124,16 +124,8 @@ package is recommended for any server code that parses untrusted XML data. The package also ships with example exploits and extended documentation on more XML exploits such as XPath injection. -`defusedexpat`_ provides a modified libexpat and a patched -:mod:`pyexpat` module that have countermeasures against entity expansion -DoS attacks. The :mod:`defusedexpat` module still allows a sane and configurable amount of entity -expansions. The modifications may be included in some future release of Python, -but will not be included in any bugfix releases of -Python because they break backward compatibility. - .. _defusedxml: https://pypi.org/project/defusedxml/ -.. _defusedexpat: https://pypi.org/project/defusedexpat/ .. _Billion Laughs: https://en.wikipedia.org/wiki/Billion_laughs .. _ZIP bomb: https://en.wikipedia.org/wiki/Zip_bomb .. _DTD: https://en.wikipedia.org/wiki/Document_type_definition From dd18001c308fb3bb65006c91d95f6639583a3420 Mon Sep 17 00:00:00 2001 From: Steve Dower Date: Sat, 5 Sep 2020 00:45:54 +0100 Subject: [PATCH 63/63] bpo-41627: Distinguish 32 and 64-bit user site packages on Windows (GH-22098) Also fixes the error message returned when sysconfig fails to interpolate a variable correctly. --- Lib/site.py | 3 ++- Lib/sysconfig.py | 22 +++++++++++-------- .../2020-09-04-21-35-28.bpo-41627.sx2KN1.rst | 2 ++ 3 files changed, 17 insertions(+), 10 deletions(-) create mode 100644 Misc/NEWS.d/next/Windows/2020-09-04-21-35-28.bpo-41627.sx2KN1.rst diff --git a/Lib/site.py b/Lib/site.py index 8979365cafc37e..4c095774729c5e 100644 --- a/Lib/site.py +++ b/Lib/site.py @@ -274,7 +274,8 @@ def _get_path(userbase): version = sys.version_info if os.name == 'nt': - return f'{userbase}\\Python{version[0]}{version[1]}\\site-packages' + ver_nodot = sys.winver.replace('.', '') + return f'{userbase}\\Python{ver_nodot}\\site-packages' if sys.platform == 'darwin' and sys._framework: return f'{userbase}/lib/python/site-packages' diff --git a/Lib/sysconfig.py b/Lib/sysconfig.py index bf04ac541e6b02..6c87b06634c457 100644 --- a/Lib/sysconfig.py +++ b/Lib/sysconfig.py @@ -53,12 +53,12 @@ }, # NOTE: When modifying "purelib" scheme, update site._get_path() too. 'nt_user': { - 'stdlib': '{userbase}/Python{py_version_nodot}', - 'platstdlib': '{userbase}/Python{py_version_nodot}', - 'purelib': '{userbase}/Python{py_version_nodot}/site-packages', - 'platlib': '{userbase}/Python{py_version_nodot}/site-packages', - 'include': '{userbase}/Python{py_version_nodot}/Include', - 'scripts': '{userbase}/Python{py_version_nodot}/Scripts', + 'stdlib': '{userbase}/Python{py_version_nodot_plat}', + 'platstdlib': '{userbase}/Python{py_version_nodot_plat}', + 'purelib': '{userbase}/Python{py_version_nodot_plat}/site-packages', + 'platlib': '{userbase}/Python{py_version_nodot_plat}/site-packages', + 'include': '{userbase}/Python{py_version_nodot_plat}/Include', + 'scripts': '{userbase}/Python{py_version_nodot_plat}/Scripts', 'data': '{userbase}', }, 'posix_user': { @@ -149,10 +149,10 @@ def is_python_build(check_home=False): def _subst_vars(s, local_vars): try: return s.format(**local_vars) - except KeyError: + except KeyError as var: try: return s.format(**os.environ) - except KeyError as var: + except KeyError: raise AttributeError('{%s}' % var) from None def _extend_dict(target_dict, other_dict): @@ -431,6 +431,7 @@ def _init_non_posix(vars): vars['EXE'] = '.exe' vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable)) + vars['TZPATH'] = '' # # public APIs @@ -543,10 +544,13 @@ def get_config_vars(*args): except AttributeError: # sys.abiflags may not be defined on all platforms. _CONFIG_VARS['abiflags'] = '' + try: + _CONFIG_VARS['py_version_nodot_plat'] = sys.winver.replace('.', '') + except AttributeError: + _CONFIG_VARS['py_version_nodot_plat'] = '' if os.name == 'nt': _init_non_posix(_CONFIG_VARS) - _CONFIG_VARS['TZPATH'] = '' if os.name == 'posix': _init_posix(_CONFIG_VARS) # For backward compatibility, see issue19555 diff --git a/Misc/NEWS.d/next/Windows/2020-09-04-21-35-28.bpo-41627.sx2KN1.rst b/Misc/NEWS.d/next/Windows/2020-09-04-21-35-28.bpo-41627.sx2KN1.rst new file mode 100644 index 00000000000000..043bd5e9341c3c --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2020-09-04-21-35-28.bpo-41627.sx2KN1.rst @@ -0,0 +1,2 @@ +The user site directory for 32-bit now includes a ``-32`` suffix to +distinguish it from the 64-bit interpreter's directory.