Skip to content

Commit

Permalink
pythongh-112438: Fix support of format units with the "e" prefix in n…
Browse files Browse the repository at this point in the history
…ested tuples in PyArg_Parse (pythongh-112439)
  • Loading branch information
serhiy-storchaka committed Nov 27, 2023
1 parent 812360f commit 4eea1e8
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 6 deletions.
28 changes: 28 additions & 0 deletions Lib/test/test_capi/test_getargs.py
Expand Up @@ -1314,6 +1314,34 @@ def test_nonascii_keywords(self):
f"'{name2}' is an invalid keyword argument"):
parse((), {name2: 1, name3: 2}, '|OO', [name, name3])

def test_nested_tuple(self):
parse = _testcapi.parse_tuple_and_keywords

self.assertEqual(parse(((1, 2, 3),), {}, '(OOO)', ['a']), (1, 2, 3))
self.assertEqual(parse((1, (2, 3), 4), {}, 'O(OO)O', ['a', 'b', 'c']),
(1, 2, 3, 4))
parse(((1, 2, 3),), {}, '(iii)', ['a'])

with self.assertRaisesRegex(TypeError,
"argument 1 must be sequence of length 2, not 3"):
parse(((1, 2, 3),), {}, '(ii)', ['a'])
with self.assertRaisesRegex(TypeError,
"argument 1 must be sequence of length 2, not 1"):
parse(((1,),), {}, '(ii)', ['a'])
with self.assertRaisesRegex(TypeError,
"argument 1 must be 2-item sequence, not int"):
parse((1,), {}, '(ii)', ['a'])
with self.assertRaisesRegex(TypeError,
"argument 1 must be 2-item sequence, not bytes"):
parse((b'ab',), {}, '(ii)', ['a'])

for f in 'es', 'et', 'es#', 'et#':
with self.assertRaises(LookupError): # empty encoding ""
parse((('a',),), {}, '(' + f + ')', ['a'])
with self.assertRaisesRegex(TypeError,
"argument 1 must be sequence of length 1, not 0"):
parse(((),), {}, '(' + f + ')', ['a'])


if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,2 @@
Fix support of format units "es", "et", "es#", and "et#" in nested tuples in
:c:func:`PyArg_ParseTuple`-like functions.
14 changes: 9 additions & 5 deletions Modules/_testcapi/getargs.c
Expand Up @@ -71,18 +71,22 @@ parse_tuple_and_keywords(PyObject *self, PyObject *args)

if (result) {
int objects_only = 1;
int count = 0;
for (const char *f = sub_format; *f; f++) {
if (Py_ISALNUM(*f) && strchr("OSUY", *f) == NULL) {
objects_only = 0;
break;
if (Py_ISALNUM(*f)) {
if (strchr("OSUY", *f) == NULL) {
objects_only = 0;
break;
}
count++;
}
}
if (objects_only) {
return_value = PyTuple_New(size);
return_value = PyTuple_New(count);
if (return_value == NULL) {
goto exit;
}
for (Py_ssize_t i = 0; i < size; i++) {
for (Py_ssize_t i = 0; i < count; i++) {
PyObject *arg = *(PyObject **)(buffers + i);
if (arg == NULL) {
arg = Py_None;
Expand Down
2 changes: 1 addition & 1 deletion Python/getargs.c
Expand Up @@ -477,7 +477,7 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
}
else if (c == ':' || c == ';' || c == '\0')
break;
else if (level == 0 && Py_ISALPHA(c))
else if (level == 0 && Py_ISALPHA(c) && c != 'e')
n++;
}

Expand Down

0 comments on commit 4eea1e8

Please sign in to comment.