cpython: 7454ca88aacb (original) (raw)
Mercurial > cpython
changeset 105683:7454ca88aacb
Issue #18896: Python function can now have more than 255 parameters. collections.namedtuple() now supports tuples with more than 255 elements. [#18896]
Serhiy Storchaka storchaka@gmail.com | |
---|---|
date | Fri, 16 Dec 2016 19:19:02 +0200 |
parents | 79d52e7d472d |
children | 25b8b5cf8e2f |
files | Doc/whatsnew/3.7.rst Include/code.h Lib/test/test_collections.py Lib/test/test_compile.py Lib/test/test_keywordonlyarg.py Lib/test/test_sys.py Misc/NEWS Objects/codeobject.c Python/ast.c Python/ceval.c |
diffstat | 10 files changed, 33 insertions(+), 49 deletions(-)[+] [-] Doc/whatsnew/3.7.rst 5 Include/code.h 7 Lib/test/test_collections.py 3 Lib/test/test_compile.py 11 Lib/test/test_keywordonlyarg.py 24 Lib/test/test_sys.py 2 Misc/NEWS 3 Objects/codeobject.c 20 Python/ast.c 5 Python/ceval.c 2 |
line wrap: on
line diff
--- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -75,8 +75,9 @@ New Features Other Language Changes ====================== -* More than 255 arguments can now be passed to a function.
- (Contributed by Serhiy Storchaka in :issue:
12844
.) +* More than 255 arguments can now be passed to a function, and a function can
- now have more than 255 parameters.
- (Contributed by Serhiy Storchaka in :issue:
12844
and :issue:18896
.) New Modules
--- a/Include/code.h +++ b/Include/code.h @@ -37,7 +37,7 @@ typedef struct { for tracebacks and debuggers; otherwise, constant de-duplication would collapse identical functions/lambdas defined on different lines. */
- Py_ssize_t co_cell2arg; / Maps cell vars which are arguments. */ PyObject co_filename; / unicode (where it was loaded from) */ PyObject co_name; / unicode (name, for reference) */ PyObject co_lnotab; / string (encoding addr<->lineno mapping) See @@ -84,9 +84,8 @@ typedef struct {
#define CO_FUTURE_GENERATOR_STOP 0x80000 /* This value is found in the co_cell2arg array when the associated cell
- variable does not correspond to an argument. The maximum number of
- arguments is 255 (indexed up to 254), so 255 work as a special flag.*/ -#define CO_CELL_NOT_AN_ARG 255
/* This should be defined if a future statement modifies the syntax. For example, when a keyword is added.
--- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -319,8 +319,7 @@ class TestNamedTuple(unittest.TestCase): self.assertEqual(Dot(1)._replace(d=999), (999,)) self.assertEqual(Dot(1)._fields, ('d',))
# n = 5000[](#l3.7)
n = 254 # SyntaxError: more than 255 arguments:[](#l3.8)
n = 5000[](#l3.9) names = list(set(''.join([choice(string.ascii_letters)[](#l3.10) for j in range(10)]) for i in range(n)))[](#l3.11) n = len(names)[](#l3.12)
--- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -401,16 +401,9 @@ if 1: self.assertNotIn((Ellipsis, Ellipsis), d) def test_annotation_limit(self):
# 16 bits are available for # of annotations, but only 8 bits are[](#l4.7)
# available for the parameter count, hence 255[](#l4.8)
# is the max. Ensure the result of too many annotations is a[](#l4.9)
# SyntaxError.[](#l4.10)
# more than 255 annotations, should compile ok[](#l4.11) s = "def f(%s): pass"[](#l4.12)
s %= ', '.join('a%d:%d' % (i,i) for i in range(256))[](#l4.13)
self.assertRaises(SyntaxError, compile, s, '?', 'exec')[](#l4.14)
# Test that the max # of annotations compiles.[](#l4.15)
s = "def f(%s): pass"[](#l4.16)
s %= ', '.join('a%d:%d' % (i,i) for i in range(255))[](#l4.17)
s %= ', '.join('a%d:%d' % (i,i) for i in range(300))[](#l4.18) compile(s, '?', 'exec')[](#l4.19)
--- a/Lib/test/test_keywordonlyarg.py +++ b/Lib/test/test_keywordonlyarg.py @@ -51,24 +51,12 @@ class KeywordOnlyArgTestCase(unittest.Te self.assertRaisesSyntaxError("def f(p, *, (k1, k2), **kw):\n pass\n") def testSyntaxForManyArguments(self):
fundef = "def f("[](#l5.7)
for i in range(255):[](#l5.8)
fundef += "i%d, "%i[](#l5.9)
fundef += "*, key=100):\n pass\n"[](#l5.10)
self.assertRaisesSyntaxError(fundef)[](#l5.11)
fundef2 = "def foo(i,*,"[](#l5.13)
for i in range(255):[](#l5.14)
fundef2 += "i%d, "%i[](#l5.15)
fundef2 += "lastarg):\n pass\n"[](#l5.16)
self.assertRaisesSyntaxError(fundef2)[](#l5.17)
# exactly 255 arguments, should compile ok[](#l5.19)
fundef3 = "def f(i,*,"[](#l5.20)
for i in range(253):[](#l5.21)
fundef3 += "i%d, "%i[](#l5.22)
fundef3 += "lastarg):\n pass\n"[](#l5.23)
compile(fundef3, "<test>", "single")[](#l5.24)
# more than 255 positional arguments, should compile ok[](#l5.25)
fundef = "def f(%s):\n pass\n" % ', '.join('i%d' % i for i in range(300))[](#l5.26)
compile(fundef, "<test>", "single")[](#l5.27)
# more than 255 keyword-only arguments, should compile ok[](#l5.28)
fundef = "def f(*, %s):\n pass\n" % ', '.join('i%d' % i for i in range(300))[](#l5.29)
compile(fundef, "<test>", "single")[](#l5.30)
def testTooManyPositionalErrorMessage(self): def f(a, b=None, *, c=None):
--- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -926,7 +926,7 @@ class SizeofTest(unittest.TestCase): def inner(): return x return inner
check(get_cell2.__code__, size('6i13P') + 1)[](#l6.7)
check(get_cell2.__code__, size('6i13P') + calcsize('n'))[](#l6.8) # complex[](#l6.9) check(complex(0,1), size('2d'))[](#l6.10) # method_descriptor (descriptor object)[](#l6.11)
--- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ What's New in Python 3.7.0 alpha 1 Core and Builtins ----------------- +- Issue #18896: Python function can now have more than 255 parameters.
- Issue #26919: On Android, operating system data is now always encoded/decoded to/from UTF-8, instead of the locale encoding to avoid inconsistencies with os.fsencode() and os.fsdecode() which are already using UTF-8.
--- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -110,7 +110,7 @@ PyCode_New(int argcount, int kwonlyargco PyObject *lnotab) { PyCodeObject *co;
- Py_ssize_t cell2arg = NULL; Py_ssize_t i, n_cellvars; / Check argument types */ @@ -142,19 +142,25 @@ PyCode_New(int argcount, int kwonlyargco if (n_cellvars) { Py_ssize_t total_args = argcount + kwonlyargcount + ((flags & CO_VARARGS) != 0) + ((flags & CO_VARKEYWORDS) != 0);
Py_ssize_t alloc_size = sizeof(unsigned char) * n_cellvars;[](#l8.16) bool used_cell2arg = false;[](#l8.17)
cell2arg = PyMem_MALLOC(alloc_size);[](#l8.18)
if (cell2arg == NULL)[](#l8.19)
cell2arg = PyMem_NEW(Py_ssize_t, n_cellvars);[](#l8.20)
if (cell2arg == NULL) {[](#l8.21)
PyErr_NoMemory();[](#l8.22) return NULL;[](#l8.23)
memset(cell2arg, CO_CELL_NOT_AN_ARG, alloc_size);[](#l8.24)
}[](#l8.25) /* Find cells which are also arguments. */[](#l8.26) for (i = 0; i < n_cellvars; i++) {[](#l8.27) Py_ssize_t j;[](#l8.28) PyObject *cell = PyTuple_GET_ITEM(cellvars, i);[](#l8.29)
cell2arg[i] = CO_CELL_NOT_AN_ARG;[](#l8.30) for (j = 0; j < total_args; j++) {[](#l8.31) PyObject *arg = PyTuple_GET_ITEM(varnames, j);[](#l8.32)
if (!PyUnicode_Compare(cell, arg)) {[](#l8.33)
int cmp = PyUnicode_Compare(cell, arg);[](#l8.34)
if (cmp == -1 && PyErr_Occurred()) {[](#l8.35)
PyMem_FREE(cell2arg);[](#l8.36)
return NULL;[](#l8.37)
}[](#l8.38)
if (cmp == 0) {[](#l8.39) cell2arg[i] = j;[](#l8.40) used_cell2arg = true;[](#l8.41) break;[](#l8.42)
@@ -449,7 +455,7 @@ code_sizeof(PyCodeObject *co, void *unus res = _PyObject_SIZE(Py_TYPE(co)); if (co->co_cell2arg != NULL && co->co_cellvars != NULL)
res += PyTuple_GET_SIZE(co->co_cellvars) * sizeof(unsigned char);[](#l8.47)
return PyLong_FromSsize_t(res); }res += PyTuple_GET_SIZE(co->co_cellvars) * sizeof(Py_ssize_t);[](#l8.48)
--- a/Python/ast.c +++ b/Python/ast.c @@ -1411,11 +1411,6 @@ ast_for_arguments(struct compiling *c, c if (!kwdefaults && nkwonlyargs) return NULL;
- if (nposargs + nkwonlyargs > 255) {
ast_error(c, n, "more than 255 arguments");[](#l9.8)
return NULL;[](#l9.9)
- }
- /* tfpdef: NAME [':' test] vfpdef: NAME */
--- a/Python/ceval.c +++ b/Python/ceval.c @@ -4100,7 +4100,7 @@ static PyObject * vars into frame. */ for (i = 0; i < PyTuple_GET_SIZE(co->co_cellvars); ++i) { PyObject *c;
int arg;[](#l10.7)
Py_ssize_t arg;[](#l10.8) /* Possibly account for the cell variable being an argument. */[](#l10.9) if (co->co_cell2arg != NULL &&[](#l10.10) (arg = co->co_cell2arg[i]) != CO_CELL_NOT_AN_ARG) {[](#l10.11)