From 06fdd71257bd6d340c7a47593ca3b522e0078313 Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Thu, 13 Jun 2024 21:05:10 +0200 Subject: [PATCH 01/43] Add `strict` argument --- Lib/test/test_itertools.py | 4 +- Python/bltinmodule.c | 130 +++++++++++++++++++++++-------------- 2 files changed, 82 insertions(+), 52 deletions(-) diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py index 53b8064c3cfe82..fd8a7c98529cf0 100644 --- a/Lib/test/test_itertools.py +++ b/Lib/test/test_itertools.py @@ -2140,10 +2140,10 @@ class subclass(cls): subclass(*args, newarg=3) for cls, args, result in testcases: - # Constructors of repeat, zip, compress accept keyword arguments. + # Constructors of repeat, zip, map, compress accept keyword arguments. # Their subclasses need overriding __new__ to support new # keyword arguments. - if cls in [repeat, zip, compress]: + if cls in [repeat, zip, map, compress]: continue with self.subTest(cls): class subclass_with_init(cls): diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index c4d3ecbeeff0e6..1d00bef62f11f9 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1303,6 +1303,7 @@ typedef struct { PyObject_HEAD PyObject *iters; PyObject *func; + int strict; } mapobject; static PyObject * @@ -1311,10 +1312,21 @@ map_new(PyTypeObject *type, PyObject *args, PyObject *kwds) PyObject *it, *iters, *func; mapobject *lz; Py_ssize_t numargs, i; + int strict = 0; - if ((type == &PyMap_Type || type->tp_init == PyMap_Type.tp_init) && - !_PyArg_NoKeywords("map", kwds)) - return NULL; + if (kwds) { + PyObject *empty = PyTuple_New(0); + if (empty == NULL) { + return NULL; + } + static char *kwlist[] = {"strict", NULL}; + int parsed = PyArg_ParseTupleAndKeywords( + empty, kwds, "|$p:map", kwlist, &strict); + Py_DECREF(empty); + if (!parsed) { + return NULL; + } + } numargs = PyTuple_Size(args); if (numargs < 2) { @@ -1346,47 +1358,7 @@ map_new(PyTypeObject *type, PyObject *args, PyObject *kwds) lz->iters = iters; func = PyTuple_GET_ITEM(args, 0); lz->func = Py_NewRef(func); - - return (PyObject *)lz; -} - -static PyObject * -map_vectorcall(PyObject *type, PyObject * const*args, - size_t nargsf, PyObject *kwnames) -{ - PyTypeObject *tp = _PyType_CAST(type); - if (tp == &PyMap_Type && !_PyArg_NoKwnames("map", kwnames)) { - return NULL; - } - - Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); - if (nargs < 2) { - PyErr_SetString(PyExc_TypeError, - "map() must have at least two arguments."); - return NULL; - } - - PyObject *iters = PyTuple_New(nargs-1); - if (iters == NULL) { - return NULL; - } - - for (int i=1; itp_alloc(tp, 0); - if (lz == NULL) { - Py_DECREF(iters); - return NULL; - } - lz->iters = iters; - lz->func = Py_NewRef(args[0]); + lz->strict = strict; return (PyObject *)lz; } @@ -1411,6 +1383,7 @@ map_traverse(mapobject *lz, visitproc visit, void *arg) static PyObject * map_next(mapobject *lz) { + Py_ssize_t i; PyObject *small_stack[_PY_FASTCALL_SMALL_STACK]; PyObject **stack; PyObject *result = NULL; @@ -1429,10 +1402,13 @@ map_next(mapobject *lz) } Py_ssize_t nargs = 0; - for (Py_ssize_t i=0; i < niters; i++) { + for (i=0; i < niters; i++) { PyObject *it = PyTuple_GET_ITEM(lz->iters, i); PyObject *val = Py_TYPE(it)->tp_iternext(it); if (val == NULL) { + if (lz->strict) { + goto check; + } goto exit; } stack[i] = val; @@ -1449,6 +1425,43 @@ map_next(mapobject *lz) PyMem_Free(stack); } return result; +check: + if (PyErr_Occurred()) { + if (!PyErr_ExceptionMatches(PyExc_StopIteration)) { + // next() on argument i raised an exception (not StopIteration) + return NULL; + } + PyErr_Clear(); + } + if (i) { + // ValueError: map() argument 2 is shorter than argument 1 + // ValueError: map() argument 3 is shorter than arguments 1-2 + const char* plural = i == 1 ? " " : "s 1-"; + return PyErr_Format(PyExc_ValueError, + "map() argument %d is shorter than argument%s%d", + i + 1, plural, i); + } + for (i = 1; i < niters; i++) { + PyObject *it = PyTuple_GET_ITEM(lz->iters, i); + PyObject *val = (*Py_TYPE(it)->tp_iternext)(it); + if (val) { + Py_DECREF(val); + const char* plural = i == 1 ? " " : "s 1-"; + return PyErr_Format(PyExc_ValueError, + "map() argument %d is longer than argument%s%d", + i + 1, plural, i); + } + if (PyErr_Occurred()) { + if (!PyErr_ExceptionMatches(PyExc_StopIteration)) { + // next() on argument i raised an exception (not StopIteration) + return NULL; + } + PyErr_Clear(); + } + // Argument i is exhausted. So far so good... + } + // All arguments are exhausted. Success! + goto exit; // Cleanup } static PyObject * @@ -1465,21 +1478,41 @@ map_reduce(mapobject *lz, PyObject *Py_UNUSED(ignored)) PyTuple_SET_ITEM(args, i+1, Py_NewRef(it)); } + if (lz->strict) { + Py_BuildValue("ONO", Py_TYPE(lz), args, Py_True); + } return Py_BuildValue("ON", Py_TYPE(lz), args); } +PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); + +static PyObject * +map_setstate(mapobject *lz, PyObject *state) +{ + int strict = PyObject_IsTrue(state); + if (strict < 0) { + return NULL; + } + lz->strict = strict; + Py_RETURN_NONE; +} + static PyMethodDef map_methods[] = { {"__reduce__", _PyCFunction_CAST(map_reduce), METH_NOARGS, reduce_doc}, + {"__setstate__", (PyCFunction)map_setstate, METH_O, setstate_doc}, {NULL, NULL} /* sentinel */ }; PyDoc_STRVAR(map_doc, -"map(function, /, *iterables)\n\ +"map(function, /, *iterables, strict=False)\n\ --\n\ \n\ Make an iterator that computes the function using arguments from\n\ -each of the iterables. Stops when the shortest iterable is exhausted."); +each of the iterables. Stops when the shortest iterable is exhausted.\n\ +\n\ +If strict is true and one of the arguments is exhausted before the others,\n\ +raise a ValueError."); PyTypeObject PyMap_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) @@ -1523,7 +1556,6 @@ PyTypeObject PyMap_Type = { PyType_GenericAlloc, /* tp_alloc */ map_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ - .tp_vectorcall = (vectorcallfunc)map_vectorcall }; @@ -2974,8 +3006,6 @@ zip_reduce(zipobject *lz, PyObject *Py_UNUSED(ignored)) return PyTuple_Pack(2, Py_TYPE(lz), lz->ittuple); } -PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); - static PyObject * zip_setstate(zipobject *lz, PyObject *state) { From a7966f81e311744cca77e41a4e29e3274f4a88d5 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Thu, 13 Jun 2024 19:12:50 +0000 Subject: [PATCH 02/43] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst b/Misc/NEWS.d/next/Core and Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst new file mode 100644 index 00000000000000..375ef003f0ebbe --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst @@ -0,0 +1 @@ +:func:`map` now supports :pep:`618`'s ``strict`` parameter, which raises a :exc:`ValueError` if the arguments are exhausted at different lengths. From 89e25d9d8f63c7931065f9ddf791310b99577ba9 Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Thu, 13 Jun 2024 21:38:15 +0200 Subject: [PATCH 03/43] Add tests --- Lib/test/test_builtin.py | 109 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 9ff0f488dc4fa9..7f5003c50eb980 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -1247,6 +1247,115 @@ def test_map_pickle(self): m2 = map(map_char, "Is this the real life?") self.check_iter_pickle(m1, list(m2), proto) + # def test_map_pickle_strict(self): + # f = lambda x, y: (x, y) + # a = (1, 2, 3) + # b = (4, 5, 6) + # t = [(1, 4), (2, 5), (3, 6)] + # for proto in range(pickle.HIGHEST_PROTOCOL + 1): + # m1 = map(f, a, b, strict=True) + # self.check_iter_pickle(m1, t, proto) + + # def test_map_pickle_strict_fail(self): + # f = lambda x, y: (x, y) + # a = (1, 2, 3) + # b = (4, 5, 6, 7) + # t = [(1, 4), (2, 5), (3, 6)] + # for proto in range(pickle.HIGHEST_PROTOCOL + 1): + # m1 = map(f, a, b, strict=True) + # m2 = pickle.loads(pickle.dumps(m1, proto)) + # self.assertEqual(self.iter_error(m1, ValueError), t) + # self.assertEqual(self.iter_error(m2, ValueError), t) + + def test_map_strict(self): + f2 = lambda x, y: (x, y) + f3 = lambda x, y, z: (x, y, z) + self.assertEqual(tuple(map(f2, (1, 2, 3), 'abc', strict=True)), + ((1, 'a'), (2, 'b'), (3, 'c'))) + self.assertRaises(ValueError, tuple, + map(f2, (1, 2, 3, 4), 'abc', strict=True)) + self.assertRaises(ValueError, tuple, + map(f2, (1, 2), 'abc', strict=True)) + self.assertRaises(ValueError, tuple, + map(f3, (1, 2), (1, 2), 'abc', strict=True)) + + def test_map_strict_iterators(self): + f3 = lambda a, b, c: (a, b, c) + x = iter(range(5)) + y = [0] + z = iter(range(5)) + self.assertRaises(ValueError, list, + (map(f3, x, y, z, strict=True))) + self.assertEqual(next(x), 2) + self.assertEqual(next(z), 1) + + def test_map_strict_error_handling(self): + + class Error(Exception): + pass + + class Iter: + def __init__(self, size): + self.size = size + def __iter__(self): + return self + def __next__(self): + self.size -= 1 + if self.size < 0: + raise Error + return self.size + + f2 = lambda x, y: (x, y) + f3 = lambda x, y, z: (x, y, z) + l1 = self.iter_error(map(f2, "AB", Iter(1), strict=True), Error) + self.assertEqual(l1, [("A", 0)]) + l2 = self.iter_error(map(f3, "AB", Iter(2), "A", strict=True), ValueError) + self.assertEqual(l2, [("A", 1, "A")]) + l3 = self.iter_error(map(f3, "AB", Iter(2), "ABC", strict=True), Error) + self.assertEqual(l3, [("A", 1, "A"), ("B", 0, "B")]) + l4 = self.iter_error(map(f2, "AB", Iter(3), strict=True), ValueError) + self.assertEqual(l4, [("A", 2), ("B", 1)]) + l5 = self.iter_error(map(f2, Iter(1), "AB", strict=True), Error) + self.assertEqual(l5, [(0, "A")]) + l6 = self.iter_error(map(f2, Iter(2), "A", strict=True), ValueError) + self.assertEqual(l6, [(1, "A")]) + l7 = self.iter_error(map(f2, Iter(2), "ABC", strict=True), Error) + self.assertEqual(l7, [(1, "A"), (0, "B")]) + l8 = self.iter_error(map(f2, Iter(3), "AB", strict=True), ValueError) + self.assertEqual(l8, [(2, "A"), (1, "B")]) + + def test_map_strict_error_handling_stopiteration(self): + + class Iter: + def __init__(self, size): + self.size = size + def __iter__(self): + return self + def __next__(self): + self.size -= 1 + if self.size < 0: + raise StopIteration + return self.size + + f2 = lambda x, y: (x, y) + f3 = lambda x, y, z: (x, y, z) + l1 = self.iter_error(map(f2, "AB", Iter(1), strict=True), ValueError) + self.assertEqual(l1, [("A", 0)]) + l2 = self.iter_error(map(f3, "AB", Iter(2), "A", strict=True), ValueError) + self.assertEqual(l2, [("A", 1, "A")]) + l3 = self.iter_error(map(f3, "AB", Iter(2), "ABC", strict=True), ValueError) + self.assertEqual(l3, [("A", 1, "A"), ("B", 0, "B")]) + l4 = self.iter_error(map(f2, "AB", Iter(3), strict=True), ValueError) + self.assertEqual(l4, [("A", 2), ("B", 1)]) + l5 = self.iter_error(map(f2, Iter(1), "AB", strict=True), ValueError) + self.assertEqual(l5, [(0, "A")]) + l6 = self.iter_error(map(f2, Iter(2), "A", strict=True), ValueError) + self.assertEqual(l6, [(1, "A")]) + l7 = self.iter_error(map(f2, Iter(2), "ABC", strict=True), ValueError) + self.assertEqual(l7, [(1, "A"), (0, "B")]) + l8 = self.iter_error(map(f2, Iter(3), "AB", strict=True), ValueError) + self.assertEqual(l8, [(2, "A"), (1, "B")]) + def test_max(self): self.assertEqual(max('123123'), '3') self.assertEqual(max(1, 2, 3), 3) From a48ebcf4c905d4180139fa6b906f9aa7b22dac2d Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Thu, 13 Jun 2024 21:48:29 +0200 Subject: [PATCH 04/43] Update commented out code --- Lib/test/test_builtin.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 7f5003c50eb980..0ade93dde9999f 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -1248,21 +1248,21 @@ def test_map_pickle(self): self.check_iter_pickle(m1, list(m2), proto) # def test_map_pickle_strict(self): - # f = lambda x, y: (x, y) + # f2 = lambda x, y: (x, y) # a = (1, 2, 3) # b = (4, 5, 6) # t = [(1, 4), (2, 5), (3, 6)] # for proto in range(pickle.HIGHEST_PROTOCOL + 1): - # m1 = map(f, a, b, strict=True) + # m1 = map(f2, a, b, strict=True) # self.check_iter_pickle(m1, t, proto) # def test_map_pickle_strict_fail(self): - # f = lambda x, y: (x, y) + # f2 = lambda x, y: (x, y) # a = (1, 2, 3) # b = (4, 5, 6, 7) # t = [(1, 4), (2, 5), (3, 6)] # for proto in range(pickle.HIGHEST_PROTOCOL + 1): - # m1 = map(f, a, b, strict=True) + # m1 = map(f2, a, b, strict=True) # m2 = pickle.loads(pickle.dumps(m1, proto)) # self.assertEqual(self.iter_error(m1, ValueError), t) # self.assertEqual(self.iter_error(m2, ValueError), t) From e4ee2fbd5e26486cc210809b48c7d67155aeeba5 Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Thu, 13 Jun 2024 21:55:47 +0200 Subject: [PATCH 05/43] Update docs --- Doc/library/functions.rst | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 1d82f92ea67857..9ead6277e78c08 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1188,14 +1188,19 @@ are always available. They are listed here in alphabetical order. unchanged from previous versions. -.. function:: map(function, iterable, *iterables) +.. function:: map(function, iterable, *iterables, strict=False) Return an iterator that applies *function* to every item of *iterable*, yielding the results. If additional *iterables* arguments are passed, *function* must take that many arguments and is applied to the items from all iterables in parallel. With multiple iterables, the iterator stops when the - shortest iterable is exhausted. For cases where the function inputs are - already arranged into argument tuples, see :func:`itertools.starmap`\. + shortest iterable is exhausted. If *strict* is ``True`` and one of the + arguments is exhausted before the others, a :exc:`ValueError` is raised. For + cases where the function inputs are already arranged into argument tuples, + see :func:`itertools.starmap`\. + + .. versionchanged:: 3.14 + Added the ``strict`` argument. .. function:: max(iterable, *, key=None) From bdd0fcb8b91bbfad94de294a9019175b0d5eb85e Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Thu, 13 Jun 2024 22:09:09 +0200 Subject: [PATCH 06/43] Fix `__reduce__()` --- Lib/test/test_builtin.py | 46 +++++++++++++++++----------------------- Python/bltinmodule.c | 2 +- 2 files changed, 21 insertions(+), 27 deletions(-) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 0ade93dde9999f..7009b83faf6f6e 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -145,6 +145,9 @@ def filter_char(arg): def map_char(arg): return chr(ord(arg)+1) +def f2(x, y): return (x, y) +def f3(x, y, z): return (x, y, z) + class BuiltinTest(unittest.TestCase): # Helper to check picklability def check_iter_pickle(self, it, seq, proto): @@ -1247,29 +1250,25 @@ def test_map_pickle(self): m2 = map(map_char, "Is this the real life?") self.check_iter_pickle(m1, list(m2), proto) - # def test_map_pickle_strict(self): - # f2 = lambda x, y: (x, y) - # a = (1, 2, 3) - # b = (4, 5, 6) - # t = [(1, 4), (2, 5), (3, 6)] - # for proto in range(pickle.HIGHEST_PROTOCOL + 1): - # m1 = map(f2, a, b, strict=True) - # self.check_iter_pickle(m1, t, proto) - - # def test_map_pickle_strict_fail(self): - # f2 = lambda x, y: (x, y) - # a = (1, 2, 3) - # b = (4, 5, 6, 7) - # t = [(1, 4), (2, 5), (3, 6)] - # for proto in range(pickle.HIGHEST_PROTOCOL + 1): - # m1 = map(f2, a, b, strict=True) - # m2 = pickle.loads(pickle.dumps(m1, proto)) - # self.assertEqual(self.iter_error(m1, ValueError), t) - # self.assertEqual(self.iter_error(m2, ValueError), t) + def test_map_pickle_strict(self): + a = (1, 2, 3) + b = (4, 5, 6) + t = [(1, 4), (2, 5), (3, 6)] + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + m1 = map(f2, a, b, strict=True) + self.check_iter_pickle(m1, t, proto) + + def test_map_pickle_strict_fail(self): + a = (1, 2, 3) + b = (4, 5, 6, 7) + t = [(1, 4), (2, 5), (3, 6)] + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + m1 = map(f2, a, b, strict=True) + m2 = pickle.loads(pickle.dumps(m1, proto)) + self.assertEqual(self.iter_error(m1, ValueError), t) + self.assertEqual(self.iter_error(m2, ValueError), t) def test_map_strict(self): - f2 = lambda x, y: (x, y) - f3 = lambda x, y, z: (x, y, z) self.assertEqual(tuple(map(f2, (1, 2, 3), 'abc', strict=True)), ((1, 'a'), (2, 'b'), (3, 'c'))) self.assertRaises(ValueError, tuple, @@ -1280,7 +1279,6 @@ def test_map_strict(self): map(f3, (1, 2), (1, 2), 'abc', strict=True)) def test_map_strict_iterators(self): - f3 = lambda a, b, c: (a, b, c) x = iter(range(5)) y = [0] z = iter(range(5)) @@ -1305,8 +1303,6 @@ def __next__(self): raise Error return self.size - f2 = lambda x, y: (x, y) - f3 = lambda x, y, z: (x, y, z) l1 = self.iter_error(map(f2, "AB", Iter(1), strict=True), Error) self.assertEqual(l1, [("A", 0)]) l2 = self.iter_error(map(f3, "AB", Iter(2), "A", strict=True), ValueError) @@ -1337,8 +1333,6 @@ def __next__(self): raise StopIteration return self.size - f2 = lambda x, y: (x, y) - f3 = lambda x, y, z: (x, y, z) l1 = self.iter_error(map(f2, "AB", Iter(1), strict=True), ValueError) self.assertEqual(l1, [("A", 0)]) l2 = self.iter_error(map(f3, "AB", Iter(2), "A", strict=True), ValueError) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 1d00bef62f11f9..beda81081570c5 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1479,7 +1479,7 @@ map_reduce(mapobject *lz, PyObject *Py_UNUSED(ignored)) } if (lz->strict) { - Py_BuildValue("ONO", Py_TYPE(lz), args, Py_True); + return Py_BuildValue("ONO", Py_TYPE(lz), args, Py_True); } return Py_BuildValue("ON", Py_TYPE(lz), args); } From 91a8450370994a435af189faa8b8c9484a0794dd Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Fri, 14 Jun 2024 09:01:57 +0200 Subject: [PATCH 07/43] Revert `map_vectorcall()` --- Python/bltinmodule.c | 58 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index beda81081570c5..274bea4f09d903 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1363,6 +1363,63 @@ map_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return (PyObject *)lz; } +static PyObject * +map_vectorcall(PyObject *type, PyObject * const*args, + size_t nargsf, PyObject *kwnames) +{ + PyTypeObject *tp = _PyType_CAST(type); + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); + int strict = 0; + + if (kwnames != NULL && PyTuple_GET_SIZE(kwnames) != 0) { + // Fallback to map_new() + PyObject *tuple = _PyTuple_FromArray(args, nargs); + if (tuple == NULL) { + return NULL; + } + PyObject *dict = _PyStack_AsDict(args + nargs, kwnames); + if (dict == NULL) { + Py_DECREF(tuple); + return NULL; + } + PyObject *ret = map_new(_PyType_CAST(type), tuple, dict); + Py_DECREF(tuple); + Py_DECREF(dict); + return ret; + } + + if (nargs < 2) { + PyErr_SetString(PyExc_TypeError, + "map() must have at least two arguments."); + return NULL; + } + + PyObject *iters = PyTuple_New(nargs-1); + if (iters == NULL) { + return NULL; + } + + for (int i=1; itp_alloc(tp, 0); + if (lz == NULL) { + Py_DECREF(iters); + return NULL; + } + lz->iters = iters; + lz->func = Py_NewRef(args[0]); + lz->strict = strict; + + return (PyObject *)lz; +} + static void map_dealloc(mapobject *lz) { @@ -1556,6 +1613,7 @@ PyTypeObject PyMap_Type = { PyType_GenericAlloc, /* tp_alloc */ map_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ + .tp_vectorcall = (vectorcallfunc)map_vectorcall }; From 2c7d5245bd42ec27c4f526a10a39a19952c256db Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Fri, 14 Jun 2024 09:03:03 +0200 Subject: [PATCH 08/43] Reduce diff --- Python/bltinmodule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 274bea4f09d903..e5e8cae3b0107b 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1365,10 +1365,9 @@ map_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static PyObject * map_vectorcall(PyObject *type, PyObject * const*args, - size_t nargsf, PyObject *kwnames) + size_t nargsf, PyObject *kwnames) { PyTypeObject *tp = _PyType_CAST(type); - Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); int strict = 0; if (kwnames != NULL && PyTuple_GET_SIZE(kwnames) != 0) { @@ -1388,6 +1387,7 @@ map_vectorcall(PyObject *type, PyObject * const*args, return ret; } + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); if (nargs < 2) { PyErr_SetString(PyExc_TypeError, "map() must have at least two arguments."); From 5ad7eb26c236438ff5ffae7d0f12d817838504b7 Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Fri, 14 Jun 2024 09:04:18 +0200 Subject: [PATCH 09/43] Never set --- Python/bltinmodule.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index e5e8cae3b0107b..6830f0eaef6931 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1368,7 +1368,6 @@ map_vectorcall(PyObject *type, PyObject * const*args, size_t nargsf, PyObject *kwnames) { PyTypeObject *tp = _PyType_CAST(type); - int strict = 0; if (kwnames != NULL && PyTuple_GET_SIZE(kwnames) != 0) { // Fallback to map_new() @@ -1415,7 +1414,7 @@ map_vectorcall(PyObject *type, PyObject * const*args, } lz->iters = iters; lz->func = Py_NewRef(args[0]); - lz->strict = strict; + lz->strict = 0; return (PyObject *)lz; } From 6d8584b44c079c6ebb163e13c1b5cb9386ee8cd6 Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Fri, 14 Jun 2024 09:05:01 +0200 Subject: [PATCH 10/43] Reduce diff 2 --- Python/bltinmodule.c | 1 - 1 file changed, 1 deletion(-) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 6830f0eaef6931..ca7a429fa4fd90 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1368,7 +1368,6 @@ map_vectorcall(PyObject *type, PyObject * const*args, size_t nargsf, PyObject *kwnames) { PyTypeObject *tp = _PyType_CAST(type); - if (kwnames != NULL && PyTuple_GET_SIZE(kwnames) != 0) { // Fallback to map_new() PyObject *tuple = _PyTuple_FromArray(args, nargs); From e436a2b82c8e9ffc0e7c7f97d9b06a4b5ca76756 Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Fri, 14 Jun 2024 09:10:38 +0200 Subject: [PATCH 11/43] Fixed undefined variable --- Python/bltinmodule.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index ca7a429fa4fd90..c87de8732529ea 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1368,6 +1368,8 @@ map_vectorcall(PyObject *type, PyObject * const*args, size_t nargsf, PyObject *kwnames) { PyTypeObject *tp = _PyType_CAST(type); + + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); if (kwnames != NULL && PyTuple_GET_SIZE(kwnames) != 0) { // Fallback to map_new() PyObject *tuple = _PyTuple_FromArray(args, nargs); @@ -1385,7 +1387,6 @@ map_vectorcall(PyObject *type, PyObject * const*args, return ret; } - Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); if (nargs < 2) { PyErr_SetString(PyExc_TypeError, "map() must have at least two arguments."); From f9a2a491c0a00e4acb341d38c38677e200dfdb35 Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Fri, 14 Jun 2024 10:20:00 +0200 Subject: [PATCH 12/43] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- Doc/library/functions.rst | 4 ++-- Python/bltinmodule.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 9ead6277e78c08..b9714ac3ee57f7 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1197,10 +1197,10 @@ are always available. They are listed here in alphabetical order. shortest iterable is exhausted. If *strict* is ``True`` and one of the arguments is exhausted before the others, a :exc:`ValueError` is raised. For cases where the function inputs are already arranged into argument tuples, - see :func:`itertools.starmap`\. + see :func:`itertools.starmap`. .. versionchanged:: 3.14 - Added the ``strict`` argument. + Added the *strict* argument. .. function:: max(iterable, *, key=None) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index c87de8732529ea..fbb3b6626bf987 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1381,7 +1381,7 @@ map_vectorcall(PyObject *type, PyObject * const*args, Py_DECREF(tuple); return NULL; } - PyObject *ret = map_new(_PyType_CAST(type), tuple, dict); + PyObject *ret = map_new(tp, tuple, dict); Py_DECREF(tuple); Py_DECREF(dict); return ret; @@ -1439,7 +1439,7 @@ map_traverse(mapobject *lz, visitproc visit, void *arg) static PyObject * map_next(mapobject *lz) { - Py_ssize_t i; + Py_ssize_t i; // Needed for error reporting PyObject *small_stack[_PY_FASTCALL_SMALL_STACK]; PyObject **stack; PyObject *result = NULL; From 301da5d0ecbb650fbaef323840fcc930c17bf639 Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Wed, 19 Jun 2024 16:22:20 +0200 Subject: [PATCH 13/43] Update 2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst --- .../2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst b/Misc/NEWS.d/next/Core and Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst index 375ef003f0ebbe..9ac73c81beb078 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst @@ -1 +1,2 @@ :func:`map` now supports :pep:`618`'s ``strict`` parameter, which raises a :exc:`ValueError` if the arguments are exhausted at different lengths. +(Contributed by Wannes Boeykens in :gh:`120503`.) From fb1c37910a7e767cfaea6f6a651256c6df1687af Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Wed, 19 Jun 2024 16:26:40 +0200 Subject: [PATCH 14/43] Update whatsnew --- Doc/whatsnew/3.14.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 804d39ab64646d..0043eb505d2eb0 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -75,7 +75,9 @@ New Features Other Language Changes ====================== - +* :func:`map` now supports :pep:`618`'s ``strict`` parameter, which raises a + :exc:`ValueError` if the arguments are exhausted at different lengths. + (Contributed by Wannes Boeykens in :gh:`119793`.) New Modules =========== From 255e3a26580da395dddb83df73b564a4164052bc Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Wed, 19 Jun 2024 16:27:26 +0200 Subject: [PATCH 15/43] Fix pr number --- .../2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst b/Misc/NEWS.d/next/Core and Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst index 9ac73c81beb078..12fd060aa3efa0 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst @@ -1,2 +1,2 @@ :func:`map` now supports :pep:`618`'s ``strict`` parameter, which raises a :exc:`ValueError` if the arguments are exhausted at different lengths. -(Contributed by Wannes Boeykens in :gh:`120503`.) +(Contributed by Wannes Boeykens in :gh:`119793`.) From d1c17695ba049b4117411b5013f8d5e5d10ee5de Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Wed, 19 Jun 2024 16:35:06 +0200 Subject: [PATCH 16/43] Fix signature --- Doc/library/functions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index b9714ac3ee57f7..3c549f28b481d7 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1188,7 +1188,7 @@ are always available. They are listed here in alphabetical order. unchanged from previous versions. -.. function:: map(function, iterable, *iterables, strict=False) +.. function:: map(function, iterable, /, *iterables, strict=False) Return an iterator that applies *function* to every item of *iterable*, yielding the results. If additional *iterables* arguments are passed, From 6d209763022345f09370a53cc425028849c7273c Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Wed, 19 Jun 2024 16:40:09 +0200 Subject: [PATCH 17/43] Add comment --- Lib/test/test_builtin.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 7009b83faf6f6e..f8ea8eecbec50e 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -1250,6 +1250,8 @@ def test_map_pickle(self): m2 = map(map_char, "Is this the real life?") self.check_iter_pickle(m1, list(m2), proto) + # strict map tests based on strict zip tests + def test_map_pickle_strict(self): a = (1, 2, 3) b = (4, 5, 6) From c338c8f06a2f6aff908d1527aaa3f223ace94c20 Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Wed, 19 Jun 2024 16:42:08 +0200 Subject: [PATCH 18/43] Add comment 2 --- Lib/test/test_builtin.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index f8ea8eecbec50e..3e39981d6a9307 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -145,6 +145,7 @@ def filter_char(arg): def map_char(arg): return chr(ord(arg)+1) +# DON NOT replace these functions with lambda's, pickle doesn't support them def f2(x, y): return (x, y) def f3(x, y, z): return (x, y, z) From 99d9c75fc66bc4f9c3017197cd813c6fc9c9c0c0 Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Wed, 19 Jun 2024 16:42:32 +0200 Subject: [PATCH 19/43] Fix typo --- Lib/test/test_builtin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 3e39981d6a9307..e4cb46c6438b13 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -145,7 +145,7 @@ def filter_char(arg): def map_char(arg): return chr(ord(arg)+1) -# DON NOT replace these functions with lambda's, pickle doesn't support them +# DO NOT replace these functions with lambda's, pickle doesn't support them def f2(x, y): return (x, y) def f3(x, y, z): return (x, y, z) From 63522b3af99eb3e7095d1d19e4cbae16a7fc2c91 Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Wed, 19 Jun 2024 17:09:47 +0200 Subject: [PATCH 20/43] Update Doc/library/functions.rst --- Doc/library/functions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 3c549f28b481d7..4794270f2f2801 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1200,7 +1200,7 @@ are always available. They are listed here in alphabetical order. see :func:`itertools.starmap`. .. versionchanged:: 3.14 - Added the *strict* argument. + Added the *strict* parameter. .. function:: max(iterable, *, key=None) From fcb438f47b2ada4d315af182e711120e22ec6dd7 Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Wed, 19 Jun 2024 17:22:35 +0200 Subject: [PATCH 21/43] Match news entry of `zip()` --- Doc/whatsnew/3.14.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 0043eb505d2eb0..7e559d4649115a 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -75,9 +75,10 @@ New Features Other Language Changes ====================== -* :func:`map` now supports :pep:`618`'s ``strict`` parameter, which raises a - :exc:`ValueError` if the arguments are exhausted at different lengths. +* :pep:`618`: The :func:`map` function now has an optional ``strict`` flag, used + to require that all the iterables have an equal length. (Contributed by Wannes Boeykens in :gh:`119793`.) + New Modules =========== From 6e97e314c38855833f2720bd2e7e952e0b1ab407 Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Wed, 19 Jun 2024 17:25:01 +0200 Subject: [PATCH 22/43] Fix trailing whitespace --- Doc/whatsnew/3.14.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 7e559d4649115a..debd53b8c6e78d 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -78,7 +78,6 @@ Other Language Changes * :pep:`618`: The :func:`map` function now has an optional ``strict`` flag, used to require that all the iterables have an equal length. (Contributed by Wannes Boeykens in :gh:`119793`.) - New Modules =========== From 54231e04b2dddcf71f469db27598e8c663c7b027 Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Mon, 24 Jun 2024 09:32:15 +0200 Subject: [PATCH 23/43] Update 2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst --- .../2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst b/Misc/NEWS.d/next/Core and Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst index 12fd060aa3efa0..ccefe7aa1e192d 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst @@ -1,2 +1,2 @@ :func:`map` now supports :pep:`618`'s ``strict`` parameter, which raises a :exc:`ValueError` if the arguments are exhausted at different lengths. -(Contributed by Wannes Boeykens in :gh:`119793`.) +(Contributed by Wannes Boeykens.) From b5e8ac4f9099a4f44eca4a5fb0d2ff9f0ed160c2 Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Mon, 24 Jun 2024 09:46:50 +0200 Subject: [PATCH 24/43] Update 2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst --- .../2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst b/Misc/NEWS.d/next/Core and Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst index ccefe7aa1e192d..59d4dd6895459f 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst @@ -1,2 +1,2 @@ :func:`map` now supports :pep:`618`'s ``strict`` parameter, which raises a :exc:`ValueError` if the arguments are exhausted at different lengths. -(Contributed by Wannes Boeykens.) +Contributed by Wannes Boeykens. From 53f3f583a74369911eec930b40804b0c4628aba6 Mon Sep 17 00:00:00 2001 From: Nineteendo Date: Wed, 4 Sep 2024 20:57:08 +0200 Subject: [PATCH 25/43] Remove pep reference --- Doc/whatsnew/3.14.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index debd53b8c6e78d..001686a537d1fe 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -75,8 +75,8 @@ New Features Other Language Changes ====================== -* :pep:`618`: The :func:`map` function now has an optional ``strict`` flag, used - to require that all the iterables have an equal length. +* The :func:`map` function now has an optional ``strict`` flag like + :func:`zip`, used to require that all the iterables have an equal length. (Contributed by Wannes Boeykens in :gh:`119793`.) New Modules From 9a2c0fda1d5c0ff210eb72b1c504bb6201a09a40 Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Thu, 3 Oct 2024 20:30:30 +0200 Subject: [PATCH 26/43] Make tests more maintainable --- Lib/test/test_builtin.py | 51 ++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 39fab5e0591aa8..b017544ba1d720 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -148,9 +148,8 @@ def filter_char(arg): def map_char(arg): return chr(ord(arg)+1) -# DO NOT replace these functions with lambda's, pickle doesn't support them -def f2(x, y): return (x, y) -def f3(x, y, z): return (x, y, z) +def pack(*args): + return args class BuiltinTest(unittest.TestCase): # Helper to check picklability @@ -1280,7 +1279,7 @@ def test_map_pickle_strict(self): b = (4, 5, 6) t = [(1, 4), (2, 5), (3, 6)] for proto in range(pickle.HIGHEST_PROTOCOL + 1): - m1 = map(f2, a, b, strict=True) + m1 = map(pack, a, b, strict=True) self.check_iter_pickle(m1, t, proto) def test_map_pickle_strict_fail(self): @@ -1288,27 +1287,27 @@ def test_map_pickle_strict_fail(self): b = (4, 5, 6, 7) t = [(1, 4), (2, 5), (3, 6)] for proto in range(pickle.HIGHEST_PROTOCOL + 1): - m1 = map(f2, a, b, strict=True) + m1 = map(pack, a, b, strict=True) m2 = pickle.loads(pickle.dumps(m1, proto)) self.assertEqual(self.iter_error(m1, ValueError), t) self.assertEqual(self.iter_error(m2, ValueError), t) def test_map_strict(self): - self.assertEqual(tuple(map(f2, (1, 2, 3), 'abc', strict=True)), + self.assertEqual(tuple(map(pack, (1, 2, 3), 'abc', strict=True)), ((1, 'a'), (2, 'b'), (3, 'c'))) self.assertRaises(ValueError, tuple, - map(f2, (1, 2, 3, 4), 'abc', strict=True)) + map(pack, (1, 2, 3, 4), 'abc', strict=True)) self.assertRaises(ValueError, tuple, - map(f2, (1, 2), 'abc', strict=True)) + map(pack, (1, 2), 'abc', strict=True)) self.assertRaises(ValueError, tuple, - map(f3, (1, 2), (1, 2), 'abc', strict=True)) + map(pack, (1, 2), (1, 2), 'abc', strict=True)) def test_map_strict_iterators(self): x = iter(range(5)) y = [0] z = iter(range(5)) self.assertRaises(ValueError, list, - (map(f3, x, y, z, strict=True))) + (map(pack, x, y, z, strict=True))) self.assertEqual(next(x), 2) self.assertEqual(next(z), 1) @@ -1328,21 +1327,21 @@ def __next__(self): raise Error return self.size - l1 = self.iter_error(map(f2, "AB", Iter(1), strict=True), Error) + l1 = self.iter_error(map(pack, "AB", Iter(1), strict=True), Error) self.assertEqual(l1, [("A", 0)]) - l2 = self.iter_error(map(f3, "AB", Iter(2), "A", strict=True), ValueError) + l2 = self.iter_error(map(pack, "AB", Iter(2), "A", strict=True), ValueError) self.assertEqual(l2, [("A", 1, "A")]) - l3 = self.iter_error(map(f3, "AB", Iter(2), "ABC", strict=True), Error) + l3 = self.iter_error(map(pack, "AB", Iter(2), "ABC", strict=True), Error) self.assertEqual(l3, [("A", 1, "A"), ("B", 0, "B")]) - l4 = self.iter_error(map(f2, "AB", Iter(3), strict=True), ValueError) + l4 = self.iter_error(map(pack, "AB", Iter(3), strict=True), ValueError) self.assertEqual(l4, [("A", 2), ("B", 1)]) - l5 = self.iter_error(map(f2, Iter(1), "AB", strict=True), Error) + l5 = self.iter_error(map(pack, Iter(1), "AB", strict=True), Error) self.assertEqual(l5, [(0, "A")]) - l6 = self.iter_error(map(f2, Iter(2), "A", strict=True), ValueError) + l6 = self.iter_error(map(pack, Iter(2), "A", strict=True), ValueError) self.assertEqual(l6, [(1, "A")]) - l7 = self.iter_error(map(f2, Iter(2), "ABC", strict=True), Error) + l7 = self.iter_error(map(pack, Iter(2), "ABC", strict=True), Error) self.assertEqual(l7, [(1, "A"), (0, "B")]) - l8 = self.iter_error(map(f2, Iter(3), "AB", strict=True), ValueError) + l8 = self.iter_error(map(pack, Iter(3), "AB", strict=True), ValueError) self.assertEqual(l8, [(2, "A"), (1, "B")]) def test_map_strict_error_handling_stopiteration(self): @@ -1358,21 +1357,21 @@ def __next__(self): raise StopIteration return self.size - l1 = self.iter_error(map(f2, "AB", Iter(1), strict=True), ValueError) + l1 = self.iter_error(map(pack, "AB", Iter(1), strict=True), ValueError) self.assertEqual(l1, [("A", 0)]) - l2 = self.iter_error(map(f3, "AB", Iter(2), "A", strict=True), ValueError) + l2 = self.iter_error(map(pack, "AB", Iter(2), "A", strict=True), ValueError) self.assertEqual(l2, [("A", 1, "A")]) - l3 = self.iter_error(map(f3, "AB", Iter(2), "ABC", strict=True), ValueError) + l3 = self.iter_error(map(pack, "AB", Iter(2), "ABC", strict=True), ValueError) self.assertEqual(l3, [("A", 1, "A"), ("B", 0, "B")]) - l4 = self.iter_error(map(f2, "AB", Iter(3), strict=True), ValueError) + l4 = self.iter_error(map(pack, "AB", Iter(3), strict=True), ValueError) self.assertEqual(l4, [("A", 2), ("B", 1)]) - l5 = self.iter_error(map(f2, Iter(1), "AB", strict=True), ValueError) + l5 = self.iter_error(map(pack, Iter(1), "AB", strict=True), ValueError) self.assertEqual(l5, [(0, "A")]) - l6 = self.iter_error(map(f2, Iter(2), "A", strict=True), ValueError) + l6 = self.iter_error(map(pack, Iter(2), "A", strict=True), ValueError) self.assertEqual(l6, [(1, "A")]) - l7 = self.iter_error(map(f2, Iter(2), "ABC", strict=True), ValueError) + l7 = self.iter_error(map(pack, Iter(2), "ABC", strict=True), ValueError) self.assertEqual(l7, [(1, "A"), (0, "B")]) - l8 = self.iter_error(map(f2, Iter(3), "AB", strict=True), ValueError) + l8 = self.iter_error(map(pack, Iter(3), "AB", strict=True), ValueError) self.assertEqual(l8, [(2, "A"), (1, "B")]) def test_max(self): From f75e51126acad797e83afe0452126c338ea85410 Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Thu, 10 Oct 2024 19:06:16 +0200 Subject: [PATCH 27/43] Update Python/bltinmodule.c --- Python/bltinmodule.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 6bab21e45ae36e..150b947491edb0 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1545,7 +1545,8 @@ PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); static PyObject * map_setstate(mapobject *lz, PyObject *state) { - int strict = PyObject_IsTrue(state); + // For now we keep things strict, rather than using PyObject_IsTrue(). + int strict = state == Py_True; if (strict < 0) { return NULL; } From 92134e7467d76c4c170c9b23767bf1c11d55cca3 Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Thu, 10 Oct 2024 19:10:36 +0200 Subject: [PATCH 28/43] Update Python/bltinmodule.c --- Python/bltinmodule.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 150b947491edb0..0c654a8cda99a8 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1372,19 +1372,8 @@ map_vectorcall(PyObject *type, PyObject * const*args, Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); if (kwnames != NULL && PyTuple_GET_SIZE(kwnames) != 0) { // Fallback to map_new() - PyObject *tuple = _PyTuple_FromArray(args, nargs); - if (tuple == NULL) { - return NULL; - } - PyObject *dict = _PyStack_AsDict(args + nargs, kwnames); - if (dict == NULL) { - Py_DECREF(tuple); - return NULL; - } - PyObject *ret = map_new(tp, tuple, dict); - Py_DECREF(tuple); - Py_DECREF(dict); - return ret; + PyThreadState *tstate = _PyThreadState_GET(); + return _PyObject_MakeTpCall(tstate, type, args, nargsf, kwnames); } if (nargs < 2) { From e74c3ff9999eeb7a2f85599fa7225f3b38bc8e8d Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Thu, 10 Oct 2024 19:21:17 +0200 Subject: [PATCH 29/43] Use correct variable --- Python/bltinmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 0c654a8cda99a8..f444a30a6a9a5b 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1373,7 +1373,7 @@ map_vectorcall(PyObject *type, PyObject * const*args, if (kwnames != NULL && PyTuple_GET_SIZE(kwnames) != 0) { // Fallback to map_new() PyThreadState *tstate = _PyThreadState_GET(); - return _PyObject_MakeTpCall(tstate, type, args, nargsf, kwnames); + return _PyObject_MakeTpCall(tstate, type, args, nargs, kwnames); } if (nargs < 2) { From bf7f3506e133953f8eec841f6239ee02a9832381 Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Thu, 31 Oct 2024 13:19:48 +0100 Subject: [PATCH 30/43] Update Python/bltinmodule.c Co-authored-by: Pieter Eendebak --- Python/bltinmodule.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index f444a30a6a9a5b..7695407df829ad 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1536,9 +1536,6 @@ map_setstate(mapobject *lz, PyObject *state) { // For now we keep things strict, rather than using PyObject_IsTrue(). int strict = state == Py_True; - if (strict < 0) { - return NULL; - } lz->strict = strict; Py_RETURN_NONE; } From 9cc41f2646755384d42e110c3c37c0fd7e9eaaa2 Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Thu, 31 Oct 2024 13:28:11 +0100 Subject: [PATCH 31/43] Rename 2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst to 2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst --- .../2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Misc/NEWS.d/next/{Core and Builtins => Core_and_Builtins }/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst (100%) diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst b/Misc/NEWS.d/next/Core_and_Builtins /2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst similarity index 100% rename from Misc/NEWS.d/next/Core and Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst rename to Misc/NEWS.d/next/Core_and_Builtins /2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst From f68610187cbf003775446d538bd0bb3b479b48bb Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Thu, 31 Oct 2024 15:04:43 +0100 Subject: [PATCH 32/43] Fix shadowed variable --- Python/bltinmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 7695407df829ad..9eac8170533a96 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1463,7 +1463,7 @@ map_next(mapobject *lz) result = _PyObject_VectorcallTstate(tstate, lz->func, stack, nargs, NULL); exit: - for (Py_ssize_t i=0; i < nargs; i++) { + for (i=0; i < nargs; i++) { Py_DECREF(stack[i]); } if (stack != small_stack) { From e524e1764dc3a5d029b155ec4b9ee21ec6f6e816 Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Thu, 31 Oct 2024 15:07:21 +0100 Subject: [PATCH 33/43] Apply suggestions from code review Co-authored-by: Erlend E. Aasland --- Python/bltinmodule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 9eac8170533a96..3ad4f8109e2f72 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1428,7 +1428,7 @@ map_traverse(mapobject *lz, visitproc visit, void *arg) static PyObject * map_next(mapobject *lz) { - Py_ssize_t i; // Needed for error reporting + Py_ssize_t i; PyObject *small_stack[_PY_FASTCALL_SMALL_STACK]; PyObject **stack; PyObject *result = NULL; @@ -1506,7 +1506,7 @@ map_next(mapobject *lz) // Argument i is exhausted. So far so good... } // All arguments are exhausted. Success! - goto exit; // Cleanup + goto exit; } static PyObject * From 91bdf2feae69a203ac2858dd4f9ff17bd781879f Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Thu, 31 Oct 2024 15:08:50 +0100 Subject: [PATCH 34/43] Rename 2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst to 2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst --- .../2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Misc/NEWS.d/next/{Core_and_Builtins => Core_and_Builtins}/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst (100%) diff --git a/Misc/NEWS.d/next/Core_and_Builtins /2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst similarity index 100% rename from Misc/NEWS.d/next/Core_and_Builtins /2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst rename to Misc/NEWS.d/next/Core_and_Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst From 39c34f154e2aa5d9cca81f019bc8926cdc2bcdd9 Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Thu, 31 Oct 2024 15:16:05 +0100 Subject: [PATCH 35/43] Use same message for news.d --- .../2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst index 59d4dd6895459f..2840986429d8af 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst @@ -1,2 +1,3 @@ -:func:`map` now supports :pep:`618`'s ``strict`` parameter, which raises a :exc:`ValueError` if the arguments are exhausted at different lengths. +The :func:`map` function now has an optional *strict* flag like +:func:`zip`, used to require that all the iterables have an equal length. Contributed by Wannes Boeykens. From ea65b2c7b0cd5df611552ebcc84be0b78679d43a Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Thu, 31 Oct 2024 15:16:31 +0100 Subject: [PATCH 36/43] Update Doc/whatsnew/3.14.rst Co-authored-by: Erlend E. Aasland --- Doc/whatsnew/3.14.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 9611569baeff31..b2b33b23be2e7c 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -175,7 +175,7 @@ Improved Error Messages Other Language Changes ====================== -* The :func:`map` function now has an optional ``strict`` flag like +* The :func:`map` function now has an optional *strict* flag like :func:`zip`, used to require that all the iterables have an equal length. (Contributed by Wannes Boeykens in :gh:`119793`.) From 45c2d0d6a5d64cdc797c5a1ffa019d05e0f2ab31 Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Thu, 31 Oct 2024 18:16:10 +0100 Subject: [PATCH 37/43] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- Doc/whatsnew/3.14.rst | 4 ++-- .../2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst | 2 +- Python/bltinmodule.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index b2b33b23be2e7c..dffd8123569daa 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -175,8 +175,8 @@ Improved Error Messages Other Language Changes ====================== -* The :func:`map` function now has an optional *strict* flag like - :func:`zip`, used to require that all the iterables have an equal length. +* The :func:`map` built-in now has an optional keyword-only *strict* flag + like :func:`zip` to check that all the iterables are of equal length. (Contributed by Wannes Boeykens in :gh:`119793`.) * Incorrect usage of :keyword:`await` and asynchronous comprehensions diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst index 2840986429d8af..310964de8e5d26 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst @@ -1,3 +1,3 @@ The :func:`map` function now has an optional *strict* flag like :func:`zip`, used to require that all the iterables have an equal length. -Contributed by Wannes Boeykens. +Patch by Wannes Boeykens. diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 3ad4f8109e2f72..74957963ef0915 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1542,7 +1542,7 @@ map_setstate(mapobject *lz, PyObject *state) static PyMethodDef map_methods[] = { {"__reduce__", _PyCFunction_CAST(map_reduce), METH_NOARGS, reduce_doc}, - {"__setstate__", (PyCFunction)map_setstate, METH_O, setstate_doc}, + {"__setstate__", _PyCFunction_CAST(map_setstate), METH_O, setstate_doc}, {NULL, NULL} /* sentinel */ }; From ad6c2a5ee838e06289178624e04a6529d64a43fc Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Thu, 31 Oct 2024 18:17:56 +0100 Subject: [PATCH 38/43] Sync with what's new --- .../2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst index 310964de8e5d26..976d6712e4b6af 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2024-06-13-19-12-49.gh-issue-119793.FDVCDk.rst @@ -1,3 +1,3 @@ -The :func:`map` function now has an optional *strict* flag like -:func:`zip`, used to require that all the iterables have an equal length. +The :func:`map` built-in now has an optional keyword-only *strict* flag +like :func:`zip` to check that all the iterables are of equal length. Patch by Wannes Boeykens. From 9ebc398d5a155856a72948cb478b63cee8285d80 Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Thu, 31 Oct 2024 18:36:06 +0100 Subject: [PATCH 39/43] Accept truthy value in setstate --- Python/bltinmodule.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 74957963ef0915..46f584e75a96c3 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1534,9 +1534,10 @@ PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); static PyObject * map_setstate(mapobject *lz, PyObject *state) { - // For now we keep things strict, rather than using PyObject_IsTrue(). - int strict = state == Py_True; - lz->strict = strict; + int strict = PyObject_IsTrue(state); + if (strict < 0) { + return NULL; + } Py_RETURN_NONE; } From d829a1790343105b5776f95db4ea5c0b53fb7f82 Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Thu, 31 Oct 2024 18:41:44 +0100 Subject: [PATCH 40/43] Fix removed line --- Python/bltinmodule.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 46f584e75a96c3..5f8eb846d92bf4 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1538,6 +1538,7 @@ map_setstate(mapobject *lz, PyObject *state) if (strict < 0) { return NULL; } + lz->strict = strict; Py_RETURN_NONE; } From d1d858fc7161a8f9d428d927e8128dd3bc8e920e Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Thu, 31 Oct 2024 18:57:46 +0100 Subject: [PATCH 41/43] Use stdbool --- Python/bltinmodule.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 5f8eb846d92bf4..fc0a0666d9c52b 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1,5 +1,6 @@ /* Built-in functions */ +#include #include "Python.h" #include "pycore_ast.h" // _PyAST_Validate() #include "pycore_call.h" // _PyObject_CallNoArgs() @@ -1303,7 +1304,7 @@ typedef struct { PyObject_HEAD PyObject *iters; PyObject *func; - int strict; + bool strict; } mapobject; static PyObject * @@ -1312,7 +1313,7 @@ map_new(PyTypeObject *type, PyObject *args, PyObject *kwds) PyObject *it, *iters, *func; mapobject *lz; Py_ssize_t numargs, i; - int strict = 0; + bool strict = false; if (kwds) { PyObject *empty = PyTuple_New(0); @@ -1403,7 +1404,7 @@ map_vectorcall(PyObject *type, PyObject * const*args, } lz->iters = iters; lz->func = Py_NewRef(args[0]); - lz->strict = 0; + lz->strict = false; return (PyObject *)lz; } @@ -2950,7 +2951,7 @@ typedef struct { Py_ssize_t tuplesize; PyObject *ittuple; /* tuple of iterators */ PyObject *result; - int strict; + bool strict; } zipobject; static PyObject * @@ -2961,7 +2962,7 @@ zip_new(PyTypeObject *type, PyObject *args, PyObject *kwds) PyObject *ittuple; /* tuple of iterators */ PyObject *result; Py_ssize_t tuplesize; - int strict = 0; + bool strict = false; if (kwds) { PyObject *empty = PyTuple_New(0); From f23caa5c2a375233866e24f5bae538f7454a1b3a Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Thu, 31 Oct 2024 19:48:58 +0100 Subject: [PATCH 42/43] Revert "Use stdbool" This reverts commit d1d858fc7161a8f9d428d927e8128dd3bc8e920e. --- Python/bltinmodule.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index fc0a0666d9c52b..5f8eb846d92bf4 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1,6 +1,5 @@ /* Built-in functions */ -#include #include "Python.h" #include "pycore_ast.h" // _PyAST_Validate() #include "pycore_call.h" // _PyObject_CallNoArgs() @@ -1304,7 +1303,7 @@ typedef struct { PyObject_HEAD PyObject *iters; PyObject *func; - bool strict; + int strict; } mapobject; static PyObject * @@ -1313,7 +1312,7 @@ map_new(PyTypeObject *type, PyObject *args, PyObject *kwds) PyObject *it, *iters, *func; mapobject *lz; Py_ssize_t numargs, i; - bool strict = false; + int strict = 0; if (kwds) { PyObject *empty = PyTuple_New(0); @@ -1404,7 +1403,7 @@ map_vectorcall(PyObject *type, PyObject * const*args, } lz->iters = iters; lz->func = Py_NewRef(args[0]); - lz->strict = false; + lz->strict = 0; return (PyObject *)lz; } @@ -2951,7 +2950,7 @@ typedef struct { Py_ssize_t tuplesize; PyObject *ittuple; /* tuple of iterators */ PyObject *result; - bool strict; + int strict; } zipobject; static PyObject * @@ -2962,7 +2961,7 @@ zip_new(PyTypeObject *type, PyObject *args, PyObject *kwds) PyObject *ittuple; /* tuple of iterators */ PyObject *result; Py_ssize_t tuplesize; - bool strict = false; + int strict = 0; if (kwds) { PyObject *empty = PyTuple_New(0); From 7e32e2c49d036de64f3becf68ba61d21c8ec30a3 Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Fri, 1 Nov 2024 16:33:10 +0100 Subject: [PATCH 43/43] Apply suggestions from code review Co-authored-by: Erlend E. Aasland --- Doc/library/functions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 08ae5c1fc9d78a..eb1e7253aeb2e0 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1199,7 +1199,7 @@ are always available. They are listed here in alphabetical order. *function* must take that many arguments and is applied to the items from all iterables in parallel. With multiple iterables, the iterator stops when the shortest iterable is exhausted. If *strict* is ``True`` and one of the - arguments is exhausted before the others, a :exc:`ValueError` is raised. For + iterables is exhausted before the others, a :exc:`ValueError` is raised. For cases where the function inputs are already arranged into argument tuples, see :func:`itertools.starmap`.