summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2023-10-14 05:50:03 (GMT)
committerGitHub <noreply@github.com>2023-10-14 05:50:03 (GMT)
commit7284e0ef84e53f80b2e60c3f51e3467d67a275f3 (patch)
treeccc8b2aecb45f767c08b9b4b934bfe99ce76ef47 /Lib
parentce298a1c1566467e7fd459c8f61478a26f42833e (diff)
downloadcpython-7284e0ef84e53f80b2e60c3f51e3467d67a275f3.zip
cpython-7284e0ef84e53f80b2e60c3f51e3467d67a275f3.tar.gz
cpython-7284e0ef84e53f80b2e60c3f51e3467d67a275f3.tar.bz2
gh-110815: Support non-ASCII keyword names in PyArg_ParseTupleAndKeywords() (GH-110816)
It already mostly worked, except in the case when invalid keyword argument with non-ASCII name was passed to function with non-ASCII parameter names. Then it crashed in the debug mode.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/test/test_capi/test_getargs.py51
1 files changed, 51 insertions, 0 deletions
diff --git a/Lib/test/test_capi/test_getargs.py b/Lib/test/test_capi/test_getargs.py
index 7fc25f8..96d34ab 100644
--- a/Lib/test/test_capi/test_getargs.py
+++ b/Lib/test/test_capi/test_getargs.py
@@ -1235,6 +1235,57 @@ class ParseTupleAndKeywords_Test(unittest.TestCase):
with self.assertRaisesRegex(SystemError, 'Empty keyword'):
parse((1,), {}, 'O|OO', ['', 'a', ''])
+ def test_nonascii_keywords(self):
+ parse = _testcapi.parse_tuple_and_keywords
+
+ for name in ('a', 'ä', 'ŷ', '㷷', '𐀀'):
+ with self.subTest(name=name):
+ self.assertEqual(parse((), {name: 1}, 'O', [name]), (1,))
+ self.assertEqual(parse((), {}, '|O', [name]), (NULL,))
+ with self.assertRaisesRegex(TypeError,
+ f"function missing required argument '{name}'"):
+ parse((), {}, 'O', [name])
+ with self.assertRaisesRegex(TypeError,
+ fr"argument for function given by name \('{name}'\) "
+ fr"and position \(1\)"):
+ parse((1,), {name: 2}, 'O|O', [name, 'b'])
+ with self.assertRaisesRegex(TypeError,
+ f"'{name}' is an invalid keyword argument"):
+ parse((), {name: 1}, '|O', ['b'])
+ with self.assertRaisesRegex(TypeError,
+ "'b' is an invalid keyword argument"):
+ parse((), {'b': 1}, '|O', [name])
+
+ invalid = name.encode() + (name.encode()[:-1] or b'\x80')
+ self.assertEqual(parse((), {}, '|O', [invalid]), (NULL,))
+ self.assertEqual(parse((1,), {'b': 2}, 'O|O', [invalid, 'b']),
+ (1, 2))
+ with self.assertRaisesRegex(TypeError,
+ f"function missing required argument '{name}\ufffd'"):
+ parse((), {}, 'O', [invalid])
+ with self.assertRaisesRegex(UnicodeDecodeError,
+ f"'utf-8' codec can't decode bytes? "):
+ parse((), {'b': 1}, '|OO', [invalid, 'b'])
+ with self.assertRaisesRegex(UnicodeDecodeError,
+ f"'utf-8' codec can't decode bytes? "):
+ parse((), {'b': 1}, '|O', [invalid])
+
+ for name2 in ('b', 'ë', 'ĉ', 'Ɐ', '𐀁'):
+ with self.subTest(name2=name2):
+ with self.assertRaisesRegex(TypeError,
+ f"'{name2}' is an invalid keyword argument"):
+ parse((), {name2: 1}, '|O', [name])
+
+ name2 = name.encode().decode('latin1')
+ if name2 != name:
+ with self.assertRaisesRegex(TypeError,
+ f"'{name2}' is an invalid keyword argument"):
+ parse((), {name2: 1}, '|O', [name])
+ name3 = name + '3'
+ with self.assertRaisesRegex(TypeError,
+ f"'{name2}' is an invalid keyword argument"):
+ parse((), {name2: 1, name3: 2}, '|OO', [name, name3])
+
class Test_testcapi(unittest.TestCase):
locals().update((name, getattr(_testcapi, name))