Python-checkins
Threads by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
April 2022
- 1 participants
- 560 discussions
April 30, 2022
https://github.com/python/cpython/commit/19a079690c29cd6a9f3fc3cb6aeb9f5a11…
commit: 19a079690c29cd6a9f3fc3cb6aeb9f5a11c491e3
branch: 3.10
author: Miss Islington (bot) <31488909+miss-islington(a)users.noreply.github.com>
committer: miss-islington <31488909+miss-islington(a)users.noreply.github.com>
date: 2022-04-30T05:31:28-07:00
summary:
bpo-43323: Fix UnicodeEncodeError in the email module (GH-32137)
It was raised if the charset itself contains characters not encodable
in UTF-8 (in particular \udcxx characters representing non-decodable
bytes in the source).
(cherry picked from commit e91dee87edcf6dee5dd78053004d76e5f05456d4)
Co-authored-by: Serhiy Storchaka <storchaka(a)gmail.com>
files:
A Misc/NEWS.d/next/Library/2022-03-27-12-40-16.bpo-43323.9mFPuI.rst
M Lib/email/_encoded_words.py
M Lib/email/_header_value_parser.py
M Lib/test/test_email/test__encoded_words.py
M Lib/test/test_email/test_email.py
M Lib/test/test_email/test_headerregistry.py
diff --git a/Lib/email/_encoded_words.py b/Lib/email/_encoded_words.py
index 295ae7eb21237..6795a606de037 100644
--- a/Lib/email/_encoded_words.py
+++ b/Lib/email/_encoded_words.py
@@ -179,15 +179,15 @@ def decode(ew):
# Turn the CTE decoded bytes into unicode.
try:
string = bstring.decode(charset)
- except UnicodeError:
+ except UnicodeDecodeError:
defects.append(errors.UndecodableBytesDefect("Encoded word "
- "contains bytes not decodable using {} charset".format(charset)))
+ f"contains bytes not decodable using {charset!r} charset"))
string = bstring.decode(charset, 'surrogateescape')
- except LookupError:
+ except (LookupError, UnicodeEncodeError):
string = bstring.decode('ascii', 'surrogateescape')
if charset.lower() != 'unknown-8bit':
- defects.append(errors.CharsetError("Unknown charset {} "
- "in encoded word; decoded as unknown bytes".format(charset)))
+ defects.append(errors.CharsetError(f"Unknown charset {charset!r} "
+ f"in encoded word; decoded as unknown bytes"))
return string, charset, lang, defects
diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py
index 51d355fbb0abc..8a8fb8bc42a95 100644
--- a/Lib/email/_header_value_parser.py
+++ b/Lib/email/_header_value_parser.py
@@ -781,7 +781,7 @@ def params(self):
else:
try:
value = value.decode(charset, 'surrogateescape')
- except LookupError:
+ except (LookupError, UnicodeEncodeError):
# XXX: there should really be a custom defect for
# unknown character set to make it easy to find,
# because otherwise unknown charset is a silent
diff --git a/Lib/test/test_email/test__encoded_words.py b/Lib/test/test_email/test__encoded_words.py
index 0b8b1de3359aa..1713962f94cae 100644
--- a/Lib/test/test_email/test__encoded_words.py
+++ b/Lib/test/test_email/test__encoded_words.py
@@ -130,6 +130,13 @@ def test_unknown_charset(self):
# XXX Should this be a new Defect instead?
defects = [errors.CharsetError])
+ def test_invalid_character_in_charset(self):
+ self._test('=?utf-8\udce2\udc80\udc9d?q?foo=ACbar?=',
+ b'foo\xacbar'.decode('ascii', 'surrogateescape'),
+ charset = 'utf-8\udce2\udc80\udc9d',
+ # XXX Should this be a new Defect instead?
+ defects = [errors.CharsetError])
+
def test_q_nonascii(self):
self._test('=?utf-8?q?=C3=89ric?=',
'Éric',
diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py
index a3ccbbbabfb32..af0ea03fedf0c 100644
--- a/Lib/test/test_email/test_email.py
+++ b/Lib/test/test_email/test_email.py
@@ -5323,6 +5323,15 @@ def test_rfc2231_unknown_encoding(self):
Content-Transfer-Encoding: 8bit
Content-Disposition: inline; filename*=X-UNKNOWN''myfile.txt
+"""
+ msg = email.message_from_string(m)
+ self.assertEqual(msg.get_filename(), 'myfile.txt')
+
+ def test_rfc2231_bad_character_in_encoding(self):
+ m = """\
+Content-Transfer-Encoding: 8bit
+Content-Disposition: inline; filename*=utf-8\udce2\udc80\udc9d''myfile.txt
+
"""
msg = email.message_from_string(m)
self.assertEqual(msg.get_filename(), 'myfile.txt')
diff --git a/Lib/test/test_email/test_headerregistry.py b/Lib/test/test_email/test_headerregistry.py
index 59fcd932e0ec4..25347ef13c214 100644
--- a/Lib/test/test_email/test_headerregistry.py
+++ b/Lib/test/test_email/test_headerregistry.py
@@ -714,6 +714,18 @@ def content_type_as_value(self,
" charset*=unknown-8bit''utf-8%E2%80%9D\n",
),
+ 'rfc2231_nonascii_in_charset_of_charset_parameter_value': (
+ "text/plain; charset*=utf-8”''utf-8%E2%80%9D",
+ 'text/plain',
+ 'text',
+ 'plain',
+ {'charset': 'utf-8”'},
+ [],
+ 'text/plain; charset="utf-8”"',
+ "Content-Type: text/plain;"
+ " charset*=utf-8''utf-8%E2%80%9D\n",
+ ),
+
'rfc2231_encoded_then_unencoded_segments': (
('application/x-foo;'
'\tname*0*="us-ascii\'en-us\'My";'
diff --git a/Misc/NEWS.d/next/Library/2022-03-27-12-40-16.bpo-43323.9mFPuI.rst b/Misc/NEWS.d/next/Library/2022-03-27-12-40-16.bpo-43323.9mFPuI.rst
new file mode 100644
index 0000000000000..98d73101d3ee5
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-03-27-12-40-16.bpo-43323.9mFPuI.rst
@@ -0,0 +1,2 @@
+Fix errors in the :mod:`email` module if the charset itself contains
+undecodable/unencodable characters.
1
0
April 30, 2022
https://github.com/python/cpython/commit/e91dee87edcf6dee5dd78053004d76e5f0…
commit: e91dee87edcf6dee5dd78053004d76e5f05456d4
branch: main
author: Serhiy Storchaka <storchaka(a)gmail.com>
committer: serhiy-storchaka <storchaka(a)gmail.com>
date: 2022-04-30T13:17:23+03:00
summary:
bpo-43323: Fix UnicodeEncodeError in the email module (GH-32137)
It was raised if the charset itself contains characters not encodable
in UTF-8 (in particular \udcxx characters representing non-decodable
bytes in the source).
files:
A Misc/NEWS.d/next/Library/2022-03-27-12-40-16.bpo-43323.9mFPuI.rst
M Lib/email/_encoded_words.py
M Lib/email/_header_value_parser.py
M Lib/test/test_email/test__encoded_words.py
M Lib/test/test_email/test_email.py
M Lib/test/test_email/test_headerregistry.py
diff --git a/Lib/email/_encoded_words.py b/Lib/email/_encoded_words.py
index 295ae7eb21237..6795a606de037 100644
--- a/Lib/email/_encoded_words.py
+++ b/Lib/email/_encoded_words.py
@@ -179,15 +179,15 @@ def decode(ew):
# Turn the CTE decoded bytes into unicode.
try:
string = bstring.decode(charset)
- except UnicodeError:
+ except UnicodeDecodeError:
defects.append(errors.UndecodableBytesDefect("Encoded word "
- "contains bytes not decodable using {} charset".format(charset)))
+ f"contains bytes not decodable using {charset!r} charset"))
string = bstring.decode(charset, 'surrogateescape')
- except LookupError:
+ except (LookupError, UnicodeEncodeError):
string = bstring.decode('ascii', 'surrogateescape')
if charset.lower() != 'unknown-8bit':
- defects.append(errors.CharsetError("Unknown charset {} "
- "in encoded word; decoded as unknown bytes".format(charset)))
+ defects.append(errors.CharsetError(f"Unknown charset {charset!r} "
+ f"in encoded word; decoded as unknown bytes"))
return string, charset, lang, defects
diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py
index 51d355fbb0abc..8a8fb8bc42a95 100644
--- a/Lib/email/_header_value_parser.py
+++ b/Lib/email/_header_value_parser.py
@@ -781,7 +781,7 @@ def params(self):
else:
try:
value = value.decode(charset, 'surrogateescape')
- except LookupError:
+ except (LookupError, UnicodeEncodeError):
# XXX: there should really be a custom defect for
# unknown character set to make it easy to find,
# because otherwise unknown charset is a silent
diff --git a/Lib/test/test_email/test__encoded_words.py b/Lib/test/test_email/test__encoded_words.py
index 0b8b1de3359aa..1713962f94cae 100644
--- a/Lib/test/test_email/test__encoded_words.py
+++ b/Lib/test/test_email/test__encoded_words.py
@@ -130,6 +130,13 @@ def test_unknown_charset(self):
# XXX Should this be a new Defect instead?
defects = [errors.CharsetError])
+ def test_invalid_character_in_charset(self):
+ self._test('=?utf-8\udce2\udc80\udc9d?q?foo=ACbar?=',
+ b'foo\xacbar'.decode('ascii', 'surrogateescape'),
+ charset = 'utf-8\udce2\udc80\udc9d',
+ # XXX Should this be a new Defect instead?
+ defects = [errors.CharsetError])
+
def test_q_nonascii(self):
self._test('=?utf-8?q?=C3=89ric?=',
'Éric',
diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py
index 933aa4cbc1959..69f883a3673f2 100644
--- a/Lib/test/test_email/test_email.py
+++ b/Lib/test/test_email/test_email.py
@@ -5356,6 +5356,15 @@ def test_rfc2231_unknown_encoding(self):
Content-Transfer-Encoding: 8bit
Content-Disposition: inline; filename*=X-UNKNOWN''myfile.txt
+"""
+ msg = email.message_from_string(m)
+ self.assertEqual(msg.get_filename(), 'myfile.txt')
+
+ def test_rfc2231_bad_character_in_encoding(self):
+ m = """\
+Content-Transfer-Encoding: 8bit
+Content-Disposition: inline; filename*=utf-8\udce2\udc80\udc9d''myfile.txt
+
"""
msg = email.message_from_string(m)
self.assertEqual(msg.get_filename(), 'myfile.txt')
diff --git a/Lib/test/test_email/test_headerregistry.py b/Lib/test/test_email/test_headerregistry.py
index 59fcd932e0ec4..25347ef13c214 100644
--- a/Lib/test/test_email/test_headerregistry.py
+++ b/Lib/test/test_email/test_headerregistry.py
@@ -714,6 +714,18 @@ def content_type_as_value(self,
" charset*=unknown-8bit''utf-8%E2%80%9D\n",
),
+ 'rfc2231_nonascii_in_charset_of_charset_parameter_value': (
+ "text/plain; charset*=utf-8”''utf-8%E2%80%9D",
+ 'text/plain',
+ 'text',
+ 'plain',
+ {'charset': 'utf-8”'},
+ [],
+ 'text/plain; charset="utf-8”"',
+ "Content-Type: text/plain;"
+ " charset*=utf-8''utf-8%E2%80%9D\n",
+ ),
+
'rfc2231_encoded_then_unencoded_segments': (
('application/x-foo;'
'\tname*0*="us-ascii\'en-us\'My";'
diff --git a/Misc/NEWS.d/next/Library/2022-03-27-12-40-16.bpo-43323.9mFPuI.rst b/Misc/NEWS.d/next/Library/2022-03-27-12-40-16.bpo-43323.9mFPuI.rst
new file mode 100644
index 0000000000000..98d73101d3ee5
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-03-27-12-40-16.bpo-43323.9mFPuI.rst
@@ -0,0 +1,2 @@
+Fix errors in the :mod:`email` module if the charset itself contains
+undecodable/unencodable characters.
1
0
gh-81548: Deprecate octal escape sequences with value larger than 0o377 (GH-91668)
by serhiy-storchaka April 30, 2022
by serhiy-storchaka April 30, 2022
April 30, 2022
https://github.com/python/cpython/commit/3483299a24e41a7f2e958369cb3573d7c2…
commit: 3483299a24e41a7f2e958369cb3573d7c2253e33
branch: main
author: Serhiy Storchaka <storchaka(a)gmail.com>
committer: serhiy-storchaka <storchaka(a)gmail.com>
date: 2022-04-30T13:16:27+03:00
summary:
gh-81548: Deprecate octal escape sequences with value larger than 0o377 (GH-91668)
files:
A Misc/NEWS.d/next/Core and Builtins/2022-04-18-20-25-01.gh-issue-81548.n3VYgp.rst
M Doc/reference/lexical_analysis.rst
M Doc/whatsnew/3.11.rst
M Lib/test/test_codecs.py
M Lib/test/test_string_literals.py
M Objects/bytesobject.c
M Objects/unicodeobject.c
M Parser/string_parser.c
diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst
index dba1a9dd2e15a..0e64a056a6eb2 100644
--- a/Doc/reference/lexical_analysis.rst
+++ b/Doc/reference/lexical_analysis.rst
@@ -596,6 +596,11 @@ Notes:
(1)
As in Standard C, up to three octal digits are accepted.
+ .. versionchanged:: 3.11
+ Octal escapes with value larger than ``0o377`` produce a :exc:`DeprecationWarning`.
+ In a future Python version they will be a :exc:`SyntaxWarning` and
+ eventually a :exc:`SyntaxError`.
+
(2)
Unlike in Standard C, exactly two hex digits are required.
diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst
index 1a692f2fe7f60..59c8dd6e44732 100644
--- a/Doc/whatsnew/3.11.rst
+++ b/Doc/whatsnew/3.11.rst
@@ -1055,6 +1055,12 @@ CPython bytecode changes
Deprecated
==========
+* Octal escapes with value larger than ``0o377`` now produce
+ a :exc:`DeprecationWarning`.
+ In a future Python version they will be a :exc:`SyntaxWarning` and
+ eventually a :exc:`SyntaxError`.
+ (Contributed by Serhiy Storchaka in :issue:`81548`.)
+
* The :mod:`lib2to3` package and ``2to3`` tool are now deprecated and may not
be able to parse Python 3.10 or newer. See the :pep:`617` (New PEG parser for
CPython). (Contributed by Victor Stinner in :issue:`40360`.)
diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py
index 5853e08819715..42c600dcb00de 100644
--- a/Lib/test/test_codecs.py
+++ b/Lib/test/test_codecs.py
@@ -1193,7 +1193,6 @@ def test_escape(self):
check(br"[\418]", b"[!8]")
check(br"[\101]", b"[A]")
check(br"[\1010]", b"[A0]")
- check(br"[\501]", b"[A]")
check(br"[\x41]", b"[A]")
check(br"[\x410]", b"[A0]")
for i in range(97, 123):
@@ -1209,6 +1208,9 @@ def test_escape(self):
check(br"\9", b"\\9")
with self.assertWarns(DeprecationWarning):
check(b"\\\xfa", b"\\\xfa")
+ for i in range(0o400, 0o1000):
+ with self.assertWarns(DeprecationWarning):
+ check(rb'\%o' % i, bytes([i & 0o377]))
def test_errors(self):
decode = codecs.escape_decode
@@ -2435,6 +2437,9 @@ def test_escape_decode(self):
check(br"\9", "\\9")
with self.assertWarns(DeprecationWarning):
check(b"\\\xfa", "\\\xfa")
+ for i in range(0o400, 0o1000):
+ with self.assertWarns(DeprecationWarning):
+ check(rb'\%o' % i, chr(i))
def test_decode_errors(self):
decode = codecs.unicode_escape_decode
diff --git a/Lib/test/test_string_literals.py b/Lib/test/test_string_literals.py
index 7231970acf19d..3a3830bcb6e96 100644
--- a/Lib/test/test_string_literals.py
+++ b/Lib/test/test_string_literals.py
@@ -116,6 +116,7 @@ def test_eval_str_invalid_escape(self):
warnings.simplefilter('always', category=DeprecationWarning)
eval("'''\n\\z'''")
self.assertEqual(len(w), 1)
+ self.assertEqual(str(w[0].message), r"invalid escape sequence '\z'")
self.assertEqual(w[0].filename, '<string>')
self.assertEqual(w[0].lineno, 1)
@@ -125,6 +126,32 @@ def test_eval_str_invalid_escape(self):
eval("'''\n\\z'''")
exc = cm.exception
self.assertEqual(w, [])
+ self.assertEqual(exc.msg, r"invalid escape sequence '\z'")
+ self.assertEqual(exc.filename, '<string>')
+ self.assertEqual(exc.lineno, 1)
+ self.assertEqual(exc.offset, 1)
+
+ def test_eval_str_invalid_octal_escape(self):
+ for i in range(0o400, 0o1000):
+ with self.assertWarns(DeprecationWarning):
+ self.assertEqual(eval(r"'\%o'" % i), chr(i))
+
+ with warnings.catch_warnings(record=True) as w:
+ warnings.simplefilter('always', category=DeprecationWarning)
+ eval("'''\n\\407'''")
+ self.assertEqual(len(w), 1)
+ self.assertEqual(str(w[0].message),
+ r"invalid octal escape sequence '\407'")
+ self.assertEqual(w[0].filename, '<string>')
+ self.assertEqual(w[0].lineno, 1)
+
+ with warnings.catch_warnings(record=True) as w:
+ warnings.simplefilter('error', category=DeprecationWarning)
+ with self.assertRaises(SyntaxError) as cm:
+ eval("'''\n\\407'''")
+ exc = cm.exception
+ self.assertEqual(w, [])
+ self.assertEqual(exc.msg, r"invalid octal escape sequence '\407'")
self.assertEqual(exc.filename, '<string>')
self.assertEqual(exc.lineno, 1)
self.assertEqual(exc.offset, 1)
@@ -166,6 +193,7 @@ def test_eval_bytes_invalid_escape(self):
warnings.simplefilter('always', category=DeprecationWarning)
eval("b'''\n\\z'''")
self.assertEqual(len(w), 1)
+ self.assertEqual(str(w[0].message), r"invalid escape sequence '\z'")
self.assertEqual(w[0].filename, '<string>')
self.assertEqual(w[0].lineno, 1)
@@ -175,6 +203,31 @@ def test_eval_bytes_invalid_escape(self):
eval("b'''\n\\z'''")
exc = cm.exception
self.assertEqual(w, [])
+ self.assertEqual(exc.msg, r"invalid escape sequence '\z'")
+ self.assertEqual(exc.filename, '<string>')
+ self.assertEqual(exc.lineno, 1)
+
+ def test_eval_bytes_invalid_octal_escape(self):
+ for i in range(0o400, 0o1000):
+ with self.assertWarns(DeprecationWarning):
+ self.assertEqual(eval(r"b'\%o'" % i), bytes([i & 0o377]))
+
+ with warnings.catch_warnings(record=True) as w:
+ warnings.simplefilter('always', category=DeprecationWarning)
+ eval("b'''\n\\407'''")
+ self.assertEqual(len(w), 1)
+ self.assertEqual(str(w[0].message),
+ r"invalid octal escape sequence '\407'")
+ self.assertEqual(w[0].filename, '<string>')
+ self.assertEqual(w[0].lineno, 1)
+
+ with warnings.catch_warnings(record=True) as w:
+ warnings.simplefilter('error', category=DeprecationWarning)
+ with self.assertRaises(SyntaxError) as cm:
+ eval("b'''\n\\407'''")
+ exc = cm.exception
+ self.assertEqual(w, [])
+ self.assertEqual(exc.msg, r"invalid octal escape sequence '\407'")
self.assertEqual(exc.filename, '<string>')
self.assertEqual(exc.lineno, 1)
diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-04-18-20-25-01.gh-issue-81548.n3VYgp.rst b/Misc/NEWS.d/next/Core and Builtins/2022-04-18-20-25-01.gh-issue-81548.n3VYgp.rst
new file mode 100644
index 0000000000000..56b1fd63b71c0
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2022-04-18-20-25-01.gh-issue-81548.n3VYgp.rst
@@ -0,0 +1,3 @@
+Octal escapes with value larger than ``0o377`` now produce a
+:exc:`DeprecationWarning`. In a future Python version they will be a
+:exc:`SyntaxWarning` and eventually a :exc:`SyntaxError`.
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index 510a836e6b152..b5066d0986c7b 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -1113,6 +1113,12 @@ PyObject *_PyBytes_DecodeEscape(const char *s,
if (s < end && '0' <= *s && *s <= '7')
c = (c<<3) + *s++ - '0';
}
+ if (c > 0377) {
+ if (*first_invalid_escape == NULL) {
+ *first_invalid_escape = s-3; /* Back up 3 chars, since we've
+ already incremented s. */
+ }
+ }
*p++ = c;
break;
case 'x':
@@ -1179,11 +1185,24 @@ PyObject *PyBytes_DecodeEscape(const char *s,
if (result == NULL)
return NULL;
if (first_invalid_escape != NULL) {
- if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
- "invalid escape sequence '\\%c'",
- (unsigned char)*first_invalid_escape) < 0) {
- Py_DECREF(result);
- return NULL;
+ unsigned char c = *first_invalid_escape;
+ if ('4' <= c && c <= '7') {
+ if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
+ "invalid octal escape sequence '\\%.3s'",
+ first_invalid_escape) < 0)
+ {
+ Py_DECREF(result);
+ return NULL;
+ }
+ }
+ else {
+ if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
+ "invalid escape sequence '\\%c'",
+ c) < 0)
+ {
+ Py_DECREF(result);
+ return NULL;
+ }
}
}
return result;
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 7768f66c95655..493307556529b 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -6404,6 +6404,12 @@ _PyUnicode_DecodeUnicodeEscapeInternal(const char *s,
ch = (ch<<3) + *s++ - '0';
}
}
+ if (ch > 0377) {
+ if (*first_invalid_escape == NULL) {
+ *first_invalid_escape = s-3; /* Back up 3 chars, since we've
+ already incremented s. */
+ }
+ }
WRITE_CHAR(ch);
continue;
@@ -6554,11 +6560,24 @@ _PyUnicode_DecodeUnicodeEscapeStateful(const char *s,
if (result == NULL)
return NULL;
if (first_invalid_escape != NULL) {
- if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
- "invalid escape sequence '\\%c'",
- (unsigned char)*first_invalid_escape) < 0) {
- Py_DECREF(result);
- return NULL;
+ unsigned char c = *first_invalid_escape;
+ if ('4' <= c && c <= '7') {
+ if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
+ "invalid octal escape sequence '\\%.3s'",
+ first_invalid_escape) < 0)
+ {
+ Py_DECREF(result);
+ return NULL;
+ }
+ }
+ else {
+ if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
+ "invalid escape sequence '\\%c'",
+ c) < 0)
+ {
+ Py_DECREF(result);
+ return NULL;
+ }
}
}
return result;
diff --git a/Parser/string_parser.c b/Parser/string_parser.c
index 65ddd46874b20..9c12d8ca101d0 100644
--- a/Parser/string_parser.c
+++ b/Parser/string_parser.c
@@ -9,10 +9,15 @@
//// STRING HANDLING FUNCTIONS ////
static int
-warn_invalid_escape_sequence(Parser *p, unsigned char first_invalid_escape_char, Token *t)
+warn_invalid_escape_sequence(Parser *p, const char *first_invalid_escape, Token *t)
{
+ unsigned char c = *first_invalid_escape;
+ int octal = ('4' <= c && c <= '7');
PyObject *msg =
- PyUnicode_FromFormat("invalid escape sequence '\\%c'", first_invalid_escape_char);
+ octal
+ ? PyUnicode_FromFormat("invalid octal escape sequence '\\%.3s'",
+ first_invalid_escape)
+ : PyUnicode_FromFormat("invalid escape sequence '\\%c'", c);
if (msg == NULL) {
return -1;
}
@@ -27,7 +32,13 @@ warn_invalid_escape_sequence(Parser *p, unsigned char first_invalid_escape_char,
since _PyPegen_raise_error uses p->tokens[p->fill - 1] for the
error location, if p->known_err_token is not set. */
p->known_err_token = t;
- RAISE_SYNTAX_ERROR("invalid escape sequence '\\%c'", first_invalid_escape_char);
+ if (octal) {
+ RAISE_SYNTAX_ERROR("invalid octal escape sequence '\\%.3s'",
+ first_invalid_escape);
+ }
+ else {
+ RAISE_SYNTAX_ERROR("invalid escape sequence '\\%c'", c);
+ }
}
Py_DECREF(msg);
return -1;
@@ -118,7 +129,7 @@ decode_unicode_with_escapes(Parser *parser, const char *s, size_t len, Token *t)
v = _PyUnicode_DecodeUnicodeEscapeInternal(s, len, NULL, NULL, &first_invalid_escape);
if (v != NULL && first_invalid_escape != NULL) {
- if (warn_invalid_escape_sequence(parser, *first_invalid_escape, t) < 0) {
+ if (warn_invalid_escape_sequence(parser, first_invalid_escape, t) < 0) {
/* We have not decref u before because first_invalid_escape points
inside u. */
Py_XDECREF(u);
@@ -140,7 +151,7 @@ decode_bytes_with_escapes(Parser *p, const char *s, Py_ssize_t len, Token *t)
}
if (first_invalid_escape != NULL) {
- if (warn_invalid_escape_sequence(p, *first_invalid_escape, t) < 0) {
+ if (warn_invalid_escape_sequence(p, first_invalid_escape, t) < 0) {
Py_DECREF(result);
return NULL;
}
@@ -357,7 +368,7 @@ fstring_compile_expr(Parser *p, const char *expr_start, const char *expr_end,
break;
}
}
-
+
if (s == expr_end) {
if (*expr_end == '!' || *expr_end == ':' || *expr_end == '=') {
RAISE_SYNTAX_ERROR("f-string: expression required before '%c'", *expr_end);
@@ -465,7 +476,7 @@ fstring_find_literal(Parser *p, const char **str, const char *end, int raw,
decode_unicode_with_escapes(). */
continue;
}
- if (ch == '{' && warn_invalid_escape_sequence(p, ch, t) < 0) {
+ if (ch == '{' && warn_invalid_escape_sequence(p, s-1, t) < 0) {
return -1;
}
}
1
0
gh-91583: AC: Fix regression for functions with defining_class (GH-91739)
by serhiy-storchaka April 30, 2022
by serhiy-storchaka April 30, 2022
April 30, 2022
https://github.com/python/cpython/commit/a055dac0b45031878a8196a8735522de01…
commit: a055dac0b45031878a8196a8735522de018491e3
branch: main
author: Serhiy Storchaka <storchaka(a)gmail.com>
committer: serhiy-storchaka <storchaka(a)gmail.com>
date: 2022-04-30T13:15:02+03:00
summary:
gh-91583: AC: Fix regression for functions with defining_class (GH-91739)
Argument Clinic now generates the same efficient code as before
adding the defining_class parameter.
files:
A Misc/NEWS.d/next/Tools-Demos/2022-04-20-14-26-14.gh-issue-91583.200qI0.rst
M Modules/_sqlite/clinic/connection.c.h
M Modules/_sre/clinic/sre.c.h
M Modules/cjkcodecs/clinic/multibytecodec.c.h
M Modules/clinic/_curses_panel.c.h
M Modules/clinic/_dbmmodule.c.h
M Modules/clinic/_gdbmmodule.c.h
M Modules/clinic/_lsprof.c.h
M Modules/clinic/_queuemodule.c.h
M Modules/clinic/_testmultiphase.c.h
M Modules/clinic/arraymodule.c.h
M Modules/clinic/md5module.c.h
M Modules/clinic/posixmodule.c.h
M Modules/clinic/pyexpat.c.h
M Modules/clinic/sha1module.c.h
M Modules/clinic/sha256module.c.h
M Modules/clinic/sha512module.c.h
M Modules/clinic/zlibmodule.c.h
M Tools/clinic/clinic.py
diff --git a/Misc/NEWS.d/next/Tools-Demos/2022-04-20-14-26-14.gh-issue-91583.200qI0.rst b/Misc/NEWS.d/next/Tools-Demos/2022-04-20-14-26-14.gh-issue-91583.200qI0.rst
new file mode 100644
index 0000000000000..bdfa71100f95a
--- /dev/null
+++ b/Misc/NEWS.d/next/Tools-Demos/2022-04-20-14-26-14.gh-issue-91583.200qI0.rst
@@ -0,0 +1,2 @@
+Fix regression in the code generated by Argument Clinic for functions with
+the ``defining_class`` parameter.
diff --git a/Modules/_sqlite/clinic/connection.c.h b/Modules/_sqlite/clinic/connection.c.h
index d4597086f4c9a..b012c4d4bbfa3 100644
--- a/Modules/_sqlite/clinic/connection.c.h
+++ b/Modules/_sqlite/clinic/connection.c.h
@@ -323,16 +323,44 @@ pysqlite_connection_create_function(pysqlite_Connection *self, PyTypeObject *cls
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"name", "narg", "func", "deterministic", NULL};
- static _PyArg_Parser _parser = {"siO|$p:create_function", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "create_function", 0};
+ PyObject *argsbuf[4];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 3;
const char *name;
int narg;
PyObject *func;
int deterministic = 0;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &name, &narg, &func, &deterministic)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (!PyUnicode_Check(args[0])) {
+ _PyArg_BadArgument("create_function", "argument 'name'", "str", args[0]);
+ goto exit;
+ }
+ Py_ssize_t name_length;
+ name = PyUnicode_AsUTF8AndSize(args[0], &name_length);
+ if (name == NULL) {
+ goto exit;
+ }
+ if (strlen(name) != (size_t)name_length) {
+ PyErr_SetString(PyExc_ValueError, "embedded null character");
+ goto exit;
+ }
+ narg = _PyLong_AsInt(args[1]);
+ if (narg == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ func = args[2];
+ if (!noptargs) {
+ goto skip_optional_kwonly;
+ }
+ deterministic = PyObject_IsTrue(args[3]);
+ if (deterministic < 0) {
goto exit;
}
+skip_optional_kwonly:
return_value = pysqlite_connection_create_function_impl(self, cls, name, narg, func, deterministic);
exit:
@@ -369,15 +397,34 @@ create_window_function(pysqlite_Connection *self, PyTypeObject *cls, PyObject *c
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"", "", "", NULL};
- static _PyArg_Parser _parser = {"siO:create_window_function", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "create_window_function", 0};
+ PyObject *argsbuf[3];
const char *name;
int num_params;
PyObject *aggregate_class;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &name, &num_params, &aggregate_class)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (!PyUnicode_Check(args[0])) {
+ _PyArg_BadArgument("create_window_function", "argument 1", "str", args[0]);
+ goto exit;
+ }
+ Py_ssize_t name_length;
+ name = PyUnicode_AsUTF8AndSize(args[0], &name_length);
+ if (name == NULL) {
+ goto exit;
+ }
+ if (strlen(name) != (size_t)name_length) {
+ PyErr_SetString(PyExc_ValueError, "embedded null character");
goto exit;
}
+ num_params = _PyLong_AsInt(args[1]);
+ if (num_params == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ aggregate_class = args[2];
return_value = create_window_function_impl(self, cls, name, num_params, aggregate_class);
exit:
@@ -406,15 +453,34 @@ pysqlite_connection_create_aggregate(pysqlite_Connection *self, PyTypeObject *cl
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"name", "n_arg", "aggregate_class", NULL};
- static _PyArg_Parser _parser = {"siO:create_aggregate", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "create_aggregate", 0};
+ PyObject *argsbuf[3];
const char *name;
int n_arg;
PyObject *aggregate_class;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &name, &n_arg, &aggregate_class)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 3, 3, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (!PyUnicode_Check(args[0])) {
+ _PyArg_BadArgument("create_aggregate", "argument 'name'", "str", args[0]);
+ goto exit;
+ }
+ Py_ssize_t name_length;
+ name = PyUnicode_AsUTF8AndSize(args[0], &name_length);
+ if (name == NULL) {
+ goto exit;
+ }
+ if (strlen(name) != (size_t)name_length) {
+ PyErr_SetString(PyExc_ValueError, "embedded null character");
+ goto exit;
+ }
+ n_arg = _PyLong_AsInt(args[1]);
+ if (n_arg == -1 && PyErr_Occurred()) {
goto exit;
}
+ aggregate_class = args[2];
return_value = pysqlite_connection_create_aggregate_impl(self, cls, name, n_arg, aggregate_class);
exit:
@@ -440,13 +506,15 @@ pysqlite_connection_set_authorizer(pysqlite_Connection *self, PyTypeObject *cls,
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"authorizer_callback", NULL};
- static _PyArg_Parser _parser = {"O:set_authorizer", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "set_authorizer", 0};
+ PyObject *argsbuf[1];
PyObject *callable;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &callable)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!args) {
goto exit;
}
+ callable = args[0];
return_value = pysqlite_connection_set_authorizer_impl(self, cls, callable);
exit:
@@ -472,12 +540,18 @@ pysqlite_connection_set_progress_handler(pysqlite_Connection *self, PyTypeObject
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"progress_handler", "n", NULL};
- static _PyArg_Parser _parser = {"Oi:set_progress_handler", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "set_progress_handler", 0};
+ PyObject *argsbuf[2];
PyObject *callable;
int n;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &callable, &n)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ callable = args[0];
+ n = _PyLong_AsInt(args[1]);
+ if (n == -1 && PyErr_Occurred()) {
goto exit;
}
return_value = pysqlite_connection_set_progress_handler_impl(self, cls, callable, n);
@@ -505,13 +579,15 @@ pysqlite_connection_set_trace_callback(pysqlite_Connection *self, PyTypeObject *
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"trace_callback", NULL};
- static _PyArg_Parser _parser = {"O:set_trace_callback", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "set_trace_callback", 0};
+ PyObject *argsbuf[1];
PyObject *callable;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &callable)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!args) {
goto exit;
}
+ callable = args[0];
return_value = pysqlite_connection_set_trace_callback_impl(self, cls, callable);
exit:
@@ -830,14 +906,29 @@ pysqlite_connection_create_collation(pysqlite_Connection *self, PyTypeObject *cl
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"", "", NULL};
- static _PyArg_Parser _parser = {"sO:create_collation", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "create_collation", 0};
+ PyObject *argsbuf[2];
const char *name;
PyObject *callable;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &name, &callable)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (!PyUnicode_Check(args[0])) {
+ _PyArg_BadArgument("create_collation", "argument 1", "str", args[0]);
+ goto exit;
+ }
+ Py_ssize_t name_length;
+ name = PyUnicode_AsUTF8AndSize(args[0], &name_length);
+ if (name == NULL) {
+ goto exit;
+ }
+ if (strlen(name) != (size_t)name_length) {
+ PyErr_SetString(PyExc_ValueError, "embedded null character");
goto exit;
}
+ callable = args[1];
return_value = pysqlite_connection_create_collation_impl(self, cls, name, callable);
exit:
@@ -1145,4 +1236,4 @@ getlimit(pysqlite_Connection *self, PyObject *arg)
#ifndef DESERIALIZE_METHODDEF
#define DESERIALIZE_METHODDEF
#endif /* !defined(DESERIALIZE_METHODDEF) */
-/*[clinic end generated code: output=be2f526e78fa65b1 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=6c9432a9fe0a4f5e input=a9049054013a1b77]*/
diff --git a/Modules/_sre/clinic/sre.c.h b/Modules/_sre/clinic/sre.c.h
index 34cbe21f14071..c1b247ef7e9dd 100644
--- a/Modules/_sre/clinic/sre.c.h
+++ b/Modules/_sre/clinic/sre.c.h
@@ -176,15 +176,51 @@ _sre_SRE_Pattern_match(PatternObject *self, PyTypeObject *cls, PyObject *const *
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"string", "pos", "endpos", NULL};
- static _PyArg_Parser _parser = {"O|nn:match", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "match", 0};
+ PyObject *argsbuf[3];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
PyObject *string;
Py_ssize_t pos = 0;
Py_ssize_t endpos = PY_SSIZE_T_MAX;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &string, &pos, &endpos)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 3, 0, argsbuf);
+ if (!args) {
goto exit;
}
+ string = args[0];
+ if (!noptargs) {
+ goto skip_optional_pos;
+ }
+ if (args[1]) {
+ {
+ Py_ssize_t ival = -1;
+ PyObject *iobj = _PyNumber_Index(args[1]);
+ if (iobj != NULL) {
+ ival = PyLong_AsSsize_t(iobj);
+ Py_DECREF(iobj);
+ }
+ if (ival == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ pos = ival;
+ }
+ if (!--noptargs) {
+ goto skip_optional_pos;
+ }
+ }
+ {
+ Py_ssize_t ival = -1;
+ PyObject *iobj = _PyNumber_Index(args[2]);
+ if (iobj != NULL) {
+ ival = PyLong_AsSsize_t(iobj);
+ Py_DECREF(iobj);
+ }
+ if (ival == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ endpos = ival;
+ }
+skip_optional_pos:
return_value = _sre_SRE_Pattern_match_impl(self, cls, string, pos, endpos);
exit:
@@ -210,15 +246,51 @@ _sre_SRE_Pattern_fullmatch(PatternObject *self, PyTypeObject *cls, PyObject *con
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"string", "pos", "endpos", NULL};
- static _PyArg_Parser _parser = {"O|nn:fullmatch", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "fullmatch", 0};
+ PyObject *argsbuf[3];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
PyObject *string;
Py_ssize_t pos = 0;
Py_ssize_t endpos = PY_SSIZE_T_MAX;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &string, &pos, &endpos)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 3, 0, argsbuf);
+ if (!args) {
goto exit;
}
+ string = args[0];
+ if (!noptargs) {
+ goto skip_optional_pos;
+ }
+ if (args[1]) {
+ {
+ Py_ssize_t ival = -1;
+ PyObject *iobj = _PyNumber_Index(args[1]);
+ if (iobj != NULL) {
+ ival = PyLong_AsSsize_t(iobj);
+ Py_DECREF(iobj);
+ }
+ if (ival == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ pos = ival;
+ }
+ if (!--noptargs) {
+ goto skip_optional_pos;
+ }
+ }
+ {
+ Py_ssize_t ival = -1;
+ PyObject *iobj = _PyNumber_Index(args[2]);
+ if (iobj != NULL) {
+ ival = PyLong_AsSsize_t(iobj);
+ Py_DECREF(iobj);
+ }
+ if (ival == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ endpos = ival;
+ }
+skip_optional_pos:
return_value = _sre_SRE_Pattern_fullmatch_impl(self, cls, string, pos, endpos);
exit:
@@ -246,15 +318,51 @@ _sre_SRE_Pattern_search(PatternObject *self, PyTypeObject *cls, PyObject *const
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"string", "pos", "endpos", NULL};
- static _PyArg_Parser _parser = {"O|nn:search", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "search", 0};
+ PyObject *argsbuf[3];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
PyObject *string;
Py_ssize_t pos = 0;
Py_ssize_t endpos = PY_SSIZE_T_MAX;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &string, &pos, &endpos)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 3, 0, argsbuf);
+ if (!args) {
goto exit;
}
+ string = args[0];
+ if (!noptargs) {
+ goto skip_optional_pos;
+ }
+ if (args[1]) {
+ {
+ Py_ssize_t ival = -1;
+ PyObject *iobj = _PyNumber_Index(args[1]);
+ if (iobj != NULL) {
+ ival = PyLong_AsSsize_t(iobj);
+ Py_DECREF(iobj);
+ }
+ if (ival == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ pos = ival;
+ }
+ if (!--noptargs) {
+ goto skip_optional_pos;
+ }
+ }
+ {
+ Py_ssize_t ival = -1;
+ PyObject *iobj = _PyNumber_Index(args[2]);
+ if (iobj != NULL) {
+ ival = PyLong_AsSsize_t(iobj);
+ Py_DECREF(iobj);
+ }
+ if (ival == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ endpos = ival;
+ }
+skip_optional_pos:
return_value = _sre_SRE_Pattern_search_impl(self, cls, string, pos, endpos);
exit:
@@ -351,15 +459,51 @@ _sre_SRE_Pattern_finditer(PatternObject *self, PyTypeObject *cls, PyObject *cons
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"string", "pos", "endpos", NULL};
- static _PyArg_Parser _parser = {"O|nn:finditer", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "finditer", 0};
+ PyObject *argsbuf[3];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
PyObject *string;
Py_ssize_t pos = 0;
Py_ssize_t endpos = PY_SSIZE_T_MAX;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &string, &pos, &endpos)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 3, 0, argsbuf);
+ if (!args) {
goto exit;
}
+ string = args[0];
+ if (!noptargs) {
+ goto skip_optional_pos;
+ }
+ if (args[1]) {
+ {
+ Py_ssize_t ival = -1;
+ PyObject *iobj = _PyNumber_Index(args[1]);
+ if (iobj != NULL) {
+ ival = PyLong_AsSsize_t(iobj);
+ Py_DECREF(iobj);
+ }
+ if (ival == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ pos = ival;
+ }
+ if (!--noptargs) {
+ goto skip_optional_pos;
+ }
+ }
+ {
+ Py_ssize_t ival = -1;
+ PyObject *iobj = _PyNumber_Index(args[2]);
+ if (iobj != NULL) {
+ ival = PyLong_AsSsize_t(iobj);
+ Py_DECREF(iobj);
+ }
+ if (ival == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ endpos = ival;
+ }
+skip_optional_pos:
return_value = _sre_SRE_Pattern_finditer_impl(self, cls, string, pos, endpos);
exit:
@@ -384,15 +528,51 @@ _sre_SRE_Pattern_scanner(PatternObject *self, PyTypeObject *cls, PyObject *const
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"string", "pos", "endpos", NULL};
- static _PyArg_Parser _parser = {"O|nn:scanner", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "scanner", 0};
+ PyObject *argsbuf[3];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
PyObject *string;
Py_ssize_t pos = 0;
Py_ssize_t endpos = PY_SSIZE_T_MAX;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &string, &pos, &endpos)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 3, 0, argsbuf);
+ if (!args) {
goto exit;
}
+ string = args[0];
+ if (!noptargs) {
+ goto skip_optional_pos;
+ }
+ if (args[1]) {
+ {
+ Py_ssize_t ival = -1;
+ PyObject *iobj = _PyNumber_Index(args[1]);
+ if (iobj != NULL) {
+ ival = PyLong_AsSsize_t(iobj);
+ Py_DECREF(iobj);
+ }
+ if (ival == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ pos = ival;
+ }
+ if (!--noptargs) {
+ goto skip_optional_pos;
+ }
+ }
+ {
+ Py_ssize_t ival = -1;
+ PyObject *iobj = _PyNumber_Index(args[2]);
+ if (iobj != NULL) {
+ ival = PyLong_AsSsize_t(iobj);
+ Py_DECREF(iobj);
+ }
+ if (ival == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ endpos = ival;
+ }
+skip_optional_pos:
return_value = _sre_SRE_Pattern_scanner_impl(self, cls, string, pos, endpos);
exit:
@@ -468,15 +648,35 @@ _sre_SRE_Pattern_sub(PatternObject *self, PyTypeObject *cls, PyObject *const *ar
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"repl", "string", "count", NULL};
- static _PyArg_Parser _parser = {"OO|n:sub", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "sub", 0};
+ PyObject *argsbuf[3];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2;
PyObject *repl;
PyObject *string;
Py_ssize_t count = 0;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &repl, &string, &count)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf);
+ if (!args) {
goto exit;
}
+ repl = args[0];
+ string = args[1];
+ if (!noptargs) {
+ goto skip_optional_pos;
+ }
+ {
+ Py_ssize_t ival = -1;
+ PyObject *iobj = _PyNumber_Index(args[2]);
+ if (iobj != NULL) {
+ ival = PyLong_AsSsize_t(iobj);
+ Py_DECREF(iobj);
+ }
+ if (ival == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ count = ival;
+ }
+skip_optional_pos:
return_value = _sre_SRE_Pattern_sub_impl(self, cls, repl, string, count);
exit:
@@ -502,15 +702,35 @@ _sre_SRE_Pattern_subn(PatternObject *self, PyTypeObject *cls, PyObject *const *a
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"repl", "string", "count", NULL};
- static _PyArg_Parser _parser = {"OO|n:subn", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "subn", 0};
+ PyObject *argsbuf[3];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2;
PyObject *repl;
PyObject *string;
Py_ssize_t count = 0;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &repl, &string, &count)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf);
+ if (!args) {
goto exit;
}
+ repl = args[0];
+ string = args[1];
+ if (!noptargs) {
+ goto skip_optional_pos;
+ }
+ {
+ Py_ssize_t ival = -1;
+ PyObject *iobj = _PyNumber_Index(args[2]);
+ if (iobj != NULL) {
+ ival = PyLong_AsSsize_t(iobj);
+ Py_DECREF(iobj);
+ }
+ if (ival == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ count = ival;
+ }
+skip_optional_pos:
return_value = _sre_SRE_Pattern_subn_impl(self, cls, repl, string, count);
exit:
@@ -882,18 +1102,11 @@ _sre_SRE_Scanner_match_impl(ScannerObject *self, PyTypeObject *cls);
static PyObject *
_sre_SRE_Scanner_match(ScannerObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":match", _keywords, 0};
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
- goto exit;
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "match() takes no arguments");
+ return NULL;
}
- return_value = _sre_SRE_Scanner_match_impl(self, cls);
-
-exit:
- return return_value;
+ return _sre_SRE_Scanner_match_impl(self, cls);
}
PyDoc_STRVAR(_sre_SRE_Scanner_search__doc__,
@@ -910,17 +1123,10 @@ _sre_SRE_Scanner_search_impl(ScannerObject *self, PyTypeObject *cls);
static PyObject *
_sre_SRE_Scanner_search(ScannerObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":search", _keywords, 0};
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
- goto exit;
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "search() takes no arguments");
+ return NULL;
}
- return_value = _sre_SRE_Scanner_search_impl(self, cls);
-
-exit:
- return return_value;
+ return _sre_SRE_Scanner_search_impl(self, cls);
}
-/*[clinic end generated code: output=9d7510a57a157a38 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=8d8200b2177cd667 input=a9049054013a1b77]*/
diff --git a/Modules/cjkcodecs/clinic/multibytecodec.c.h b/Modules/cjkcodecs/clinic/multibytecodec.c.h
index 1dfb9a1224827..60515245490f7 100644
--- a/Modules/cjkcodecs/clinic/multibytecodec.c.h
+++ b/Modules/cjkcodecs/clinic/multibytecodec.c.h
@@ -493,13 +493,15 @@ _multibytecodec_MultibyteStreamWriter_write(MultibyteStreamWriterObject *self, P
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"", NULL};
- static _PyArg_Parser _parser = {"O:write", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "write", 0};
+ PyObject *argsbuf[1];
PyObject *strobj;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &strobj)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!args) {
goto exit;
}
+ strobj = args[0];
return_value = _multibytecodec_MultibyteStreamWriter_write_impl(self, cls, strobj);
exit:
@@ -524,13 +526,15 @@ _multibytecodec_MultibyteStreamWriter_writelines(MultibyteStreamWriterObject *se
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"", NULL};
- static _PyArg_Parser _parser = {"O:writelines", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "writelines", 0};
+ PyObject *argsbuf[1];
PyObject *lines;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &lines)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!args) {
goto exit;
}
+ lines = args[0];
return_value = _multibytecodec_MultibyteStreamWriter_writelines_impl(self, cls, lines);
exit:
@@ -552,18 +556,11 @@ _multibytecodec_MultibyteStreamWriter_reset_impl(MultibyteStreamWriterObject *se
static PyObject *
_multibytecodec_MultibyteStreamWriter_reset(MultibyteStreamWriterObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":reset", _keywords, 0};
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
- goto exit;
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "reset() takes no arguments");
+ return NULL;
}
- return_value = _multibytecodec_MultibyteStreamWriter_reset_impl(self, cls);
-
-exit:
- return return_value;
+ return _multibytecodec_MultibyteStreamWriter_reset_impl(self, cls);
}
PyDoc_STRVAR(_multibytecodec___create_codec__doc__,
@@ -573,4 +570,4 @@ PyDoc_STRVAR(_multibytecodec___create_codec__doc__,
#define _MULTIBYTECODEC___CREATE_CODEC_METHODDEF \
{"__create_codec", (PyCFunction)_multibytecodec___create_codec, METH_O, _multibytecodec___create_codec__doc__},
-/*[clinic end generated code: output=8813c05077580bda input=a9049054013a1b77]*/
+/*[clinic end generated code: output=0ee00c9f6883afe9 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/_curses_panel.c.h b/Modules/clinic/_curses_panel.c.h
index 45898070b1f54..e4642b58332de 100644
--- a/Modules/clinic/_curses_panel.c.h
+++ b/Modules/clinic/_curses_panel.c.h
@@ -17,18 +17,11 @@ _curses_panel_panel_bottom_impl(PyCursesPanelObject *self, PyTypeObject *cls);
static PyObject *
_curses_panel_panel_bottom(PyCursesPanelObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":bottom", _keywords, 0};
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
- goto exit;
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "bottom() takes no arguments");
+ return NULL;
}
- return_value = _curses_panel_panel_bottom_impl(self, cls);
-
-exit:
- return return_value;
+ return _curses_panel_panel_bottom_impl(self, cls);
}
PyDoc_STRVAR(_curses_panel_panel_hide__doc__,
@@ -48,18 +41,11 @@ _curses_panel_panel_hide_impl(PyCursesPanelObject *self, PyTypeObject *cls);
static PyObject *
_curses_panel_panel_hide(PyCursesPanelObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":hide", _keywords, 0};
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
- goto exit;
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "hide() takes no arguments");
+ return NULL;
}
- return_value = _curses_panel_panel_hide_impl(self, cls);
-
-exit:
- return return_value;
+ return _curses_panel_panel_hide_impl(self, cls);
}
PyDoc_STRVAR(_curses_panel_panel_show__doc__,
@@ -77,18 +63,11 @@ _curses_panel_panel_show_impl(PyCursesPanelObject *self, PyTypeObject *cls);
static PyObject *
_curses_panel_panel_show(PyCursesPanelObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":show", _keywords, 0};
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
- goto exit;
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "show() takes no arguments");
+ return NULL;
}
- return_value = _curses_panel_panel_show_impl(self, cls);
-
-exit:
- return return_value;
+ return _curses_panel_panel_show_impl(self, cls);
}
PyDoc_STRVAR(_curses_panel_panel_top__doc__,
@@ -106,18 +85,11 @@ _curses_panel_panel_top_impl(PyCursesPanelObject *self, PyTypeObject *cls);
static PyObject *
_curses_panel_panel_top(PyCursesPanelObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":top", _keywords, 0};
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
- goto exit;
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "top() takes no arguments");
+ return NULL;
}
- return_value = _curses_panel_panel_top_impl(self, cls);
-
-exit:
- return return_value;
+ return _curses_panel_panel_top_impl(self, cls);
}
PyDoc_STRVAR(_curses_panel_panel_above__doc__,
@@ -192,12 +164,21 @@ _curses_panel_panel_move(PyCursesPanelObject *self, PyTypeObject *cls, PyObject
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"", "", NULL};
- static _PyArg_Parser _parser = {"ii:move", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "move", 0};
+ PyObject *argsbuf[2];
int y;
int x;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &y, &x)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ y = _PyLong_AsInt(args[0]);
+ if (y == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ x = _PyLong_AsInt(args[1]);
+ if (x == -1 && PyErr_Occurred()) {
goto exit;
}
return_value = _curses_panel_panel_move_impl(self, cls, y, x);
@@ -243,13 +224,19 @@ _curses_panel_panel_replace(PyCursesPanelObject *self, PyTypeObject *cls, PyObje
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"", NULL};
- static _PyArg_Parser _parser = {"O!:replace", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "replace", 0};
+ PyObject *argsbuf[1];
PyCursesWindowObject *win;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &PyCursesWindow_Type, &win)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (!PyObject_TypeCheck(args[0], &PyCursesWindow_Type)) {
+ _PyArg_BadArgument("replace", "argument 1", (&PyCursesWindow_Type)->tp_name, args[0]);
goto exit;
}
+ win = (PyCursesWindowObject *)args[0];
return_value = _curses_panel_panel_replace_impl(self, cls, win);
exit:
@@ -274,13 +261,15 @@ _curses_panel_panel_set_userptr(PyCursesPanelObject *self, PyTypeObject *cls, Py
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"", NULL};
- static _PyArg_Parser _parser = {"O:set_userptr", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "set_userptr", 0};
+ PyObject *argsbuf[1];
PyObject *obj;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &obj)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!args) {
goto exit;
}
+ obj = args[0];
return_value = _curses_panel_panel_set_userptr_impl(self, cls, obj);
exit:
@@ -303,18 +292,11 @@ _curses_panel_panel_userptr_impl(PyCursesPanelObject *self,
static PyObject *
_curses_panel_panel_userptr(PyCursesPanelObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":userptr", _keywords, 0};
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
- goto exit;
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "userptr() takes no arguments");
+ return NULL;
}
- return_value = _curses_panel_panel_userptr_impl(self, cls);
-
-exit:
- return return_value;
+ return _curses_panel_panel_userptr_impl(self, cls);
}
PyDoc_STRVAR(_curses_panel_bottom_panel__doc__,
@@ -401,4 +383,4 @@ _curses_panel_update_panels(PyObject *module, PyObject *Py_UNUSED(ignored))
{
return _curses_panel_update_panels_impl(module);
}
-/*[clinic end generated code: output=3081ef24e5560cb0 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=c552457e8067bb0a input=a9049054013a1b77]*/
diff --git a/Modules/clinic/_dbmmodule.c.h b/Modules/clinic/_dbmmodule.c.h
index f0b8220e7fee2..a8b41607221f6 100644
--- a/Modules/clinic/_dbmmodule.c.h
+++ b/Modules/clinic/_dbmmodule.c.h
@@ -35,18 +35,11 @@ _dbm_dbm_keys_impl(dbmobject *self, PyTypeObject *cls);
static PyObject *
_dbm_dbm_keys(dbmobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":keys", _keywords, 0};
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
- goto exit;
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "keys() takes no arguments");
+ return NULL;
}
- return_value = _dbm_dbm_keys_impl(self, cls);
-
-exit:
- return return_value;
+ return _dbm_dbm_keys_impl(self, cls);
}
PyDoc_STRVAR(_dbm_dbm_get__doc__,
@@ -179,4 +172,4 @@ dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
exit:
return return_value;
}
-/*[clinic end generated code: output=32ef6c0f8f2d3db9 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=492be70729515fe3 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/_gdbmmodule.c.h b/Modules/clinic/_gdbmmodule.c.h
index a40e80d8e1a7b..ced48b99ed325 100644
--- a/Modules/clinic/_gdbmmodule.c.h
+++ b/Modules/clinic/_gdbmmodule.c.h
@@ -104,18 +104,11 @@ _gdbm_gdbm_keys_impl(gdbmobject *self, PyTypeObject *cls);
static PyObject *
_gdbm_gdbm_keys(gdbmobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":keys", _keywords, 0};
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
- goto exit;
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "keys() takes no arguments");
+ return NULL;
}
- return_value = _gdbm_gdbm_keys_impl(self, cls);
-
-exit:
- return return_value;
+ return _gdbm_gdbm_keys_impl(self, cls);
}
PyDoc_STRVAR(_gdbm_gdbm_firstkey__doc__,
@@ -137,18 +130,11 @@ _gdbm_gdbm_firstkey_impl(gdbmobject *self, PyTypeObject *cls);
static PyObject *
_gdbm_gdbm_firstkey(gdbmobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":firstkey", _keywords, 0};
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
- goto exit;
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "firstkey() takes no arguments");
+ return NULL;
}
- return_value = _gdbm_gdbm_firstkey_impl(self, cls);
-
-exit:
- return return_value;
+ return _gdbm_gdbm_firstkey_impl(self, cls);
}
PyDoc_STRVAR(_gdbm_gdbm_nextkey__doc__,
@@ -212,18 +198,11 @@ _gdbm_gdbm_reorganize_impl(gdbmobject *self, PyTypeObject *cls);
static PyObject *
_gdbm_gdbm_reorganize(gdbmobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":reorganize", _keywords, 0};
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
- goto exit;
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "reorganize() takes no arguments");
+ return NULL;
}
- return_value = _gdbm_gdbm_reorganize_impl(self, cls);
-
-exit:
- return return_value;
+ return _gdbm_gdbm_reorganize_impl(self, cls);
}
PyDoc_STRVAR(_gdbm_gdbm_sync__doc__,
@@ -244,18 +223,11 @@ _gdbm_gdbm_sync_impl(gdbmobject *self, PyTypeObject *cls);
static PyObject *
_gdbm_gdbm_sync(gdbmobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":sync", _keywords, 0};
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
- goto exit;
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "sync() takes no arguments");
+ return NULL;
}
- return_value = _gdbm_gdbm_sync_impl(self, cls);
-
-exit:
- return return_value;
+ return _gdbm_gdbm_sync_impl(self, cls);
}
PyDoc_STRVAR(dbmopen__doc__,
@@ -333,4 +305,4 @@ dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
exit:
return return_value;
}
-/*[clinic end generated code: output=63c507f93d84a3a4 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=fe7a0812eb560b23 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/_lsprof.c.h b/Modules/clinic/_lsprof.c.h
index 5d9c209eab856..b0adb746974ab 100644
--- a/Modules/clinic/_lsprof.c.h
+++ b/Modules/clinic/_lsprof.c.h
@@ -39,17 +39,10 @@ _lsprof_Profiler_getstats_impl(ProfilerObject *self, PyTypeObject *cls);
static PyObject *
_lsprof_Profiler_getstats(ProfilerObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":getstats", _keywords, 0};
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
- goto exit;
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "getstats() takes no arguments");
+ return NULL;
}
- return_value = _lsprof_Profiler_getstats_impl(self, cls);
-
-exit:
- return return_value;
+ return _lsprof_Profiler_getstats_impl(self, cls);
}
-/*[clinic end generated code: output=b4727cfebecdd22d input=a9049054013a1b77]*/
+/*[clinic end generated code: output=57c7b6b0b8666429 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/_queuemodule.c.h b/Modules/clinic/_queuemodule.c.h
index 22d2e992b6398..056a8ef52e00f 100644
--- a/Modules/clinic/_queuemodule.c.h
+++ b/Modules/clinic/_queuemodule.c.h
@@ -146,14 +146,30 @@ _queue_SimpleQueue_get(simplequeueobject *self, PyTypeObject *cls, PyObject *con
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"block", "timeout", NULL};
- static _PyArg_Parser _parser = {"|pO:get", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "get", 0};
+ PyObject *argsbuf[2];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
int block = 1;
PyObject *timeout_obj = Py_None;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &block, &timeout_obj)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 2, 0, argsbuf);
+ if (!args) {
goto exit;
}
+ if (!noptargs) {
+ goto skip_optional_pos;
+ }
+ if (args[0]) {
+ block = PyObject_IsTrue(args[0]);
+ if (block < 0) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_pos;
+ }
+ }
+ timeout_obj = args[1];
+skip_optional_pos:
return_value = _queue_SimpleQueue_get_impl(self, cls, block, timeout_obj);
exit:
@@ -179,18 +195,11 @@ _queue_SimpleQueue_get_nowait_impl(simplequeueobject *self,
static PyObject *
_queue_SimpleQueue_get_nowait(simplequeueobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":get_nowait", _keywords, 0};
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
- goto exit;
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "get_nowait() takes no arguments");
+ return NULL;
}
- return_value = _queue_SimpleQueue_get_nowait_impl(self, cls);
-
-exit:
- return return_value;
+ return _queue_SimpleQueue_get_nowait_impl(self, cls);
}
PyDoc_STRVAR(_queue_SimpleQueue_empty__doc__,
@@ -248,4 +257,4 @@ _queue_SimpleQueue_qsize(simplequeueobject *self, PyObject *Py_UNUSED(ignored))
exit:
return return_value;
}
-/*[clinic end generated code: output=acfaf0191d8935db input=a9049054013a1b77]*/
+/*[clinic end generated code: output=36301c405a858f39 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/_testmultiphase.c.h b/Modules/clinic/_testmultiphase.c.h
index b8ee93c6e19ea..753670934bf81 100644
--- a/Modules/clinic/_testmultiphase.c.h
+++ b/Modules/clinic/_testmultiphase.c.h
@@ -21,18 +21,11 @@ _testmultiphase_StateAccessType_get_defining_module_impl(StateAccessTypeObject *
static PyObject *
_testmultiphase_StateAccessType_get_defining_module(StateAccessTypeObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":get_defining_module", _keywords, 0};
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
- goto exit;
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "get_defining_module() takes no arguments");
+ return NULL;
}
- return_value = _testmultiphase_StateAccessType_get_defining_module_impl(self, cls);
-
-exit:
- return return_value;
+ return _testmultiphase_StateAccessType_get_defining_module_impl(self, cls);
}
PyDoc_STRVAR(_testmultiphase_StateAccessType_getmodulebydef_bad_def__doc__,
@@ -51,18 +44,11 @@ _testmultiphase_StateAccessType_getmodulebydef_bad_def_impl(StateAccessTypeObjec
static PyObject *
_testmultiphase_StateAccessType_getmodulebydef_bad_def(StateAccessTypeObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":getmodulebydef_bad_def", _keywords, 0};
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
- goto exit;
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "getmodulebydef_bad_def() takes no arguments");
+ return NULL;
}
- return_value = _testmultiphase_StateAccessType_getmodulebydef_bad_def_impl(self, cls);
-
-exit:
- return return_value;
+ return _testmultiphase_StateAccessType_getmodulebydef_bad_def_impl(self, cls);
}
PyDoc_STRVAR(_testmultiphase_StateAccessType_increment_count_clinic__doc__,
@@ -88,14 +74,37 @@ _testmultiphase_StateAccessType_increment_count_clinic(StateAccessTypeObject *se
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"n", "twice", NULL};
- static _PyArg_Parser _parser = {"|i$p:increment_count_clinic", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "increment_count_clinic", 0};
+ PyObject *argsbuf[2];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
int n = 1;
int twice = 0;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &n, &twice)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
+ if (!args) {
goto exit;
}
+ if (!noptargs) {
+ goto skip_optional_pos;
+ }
+ if (args[0]) {
+ n = _PyLong_AsInt(args[0]);
+ if (n == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_pos;
+ }
+ }
+skip_optional_pos:
+ if (!noptargs) {
+ goto skip_optional_kwonly;
+ }
+ twice = PyObject_IsTrue(args[1]);
+ if (twice < 0) {
+ goto exit;
+ }
+skip_optional_kwonly:
return_value = _testmultiphase_StateAccessType_increment_count_clinic_impl(self, cls, n, twice);
exit:
@@ -118,17 +127,10 @@ _testmultiphase_StateAccessType_get_count_impl(StateAccessTypeObject *self,
static PyObject *
_testmultiphase_StateAccessType_get_count(StateAccessTypeObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":get_count", _keywords, 0};
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
- goto exit;
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "get_count() takes no arguments");
+ return NULL;
}
- return_value = _testmultiphase_StateAccessType_get_count_impl(self, cls);
-
-exit:
- return return_value;
+ return _testmultiphase_StateAccessType_get_count_impl(self, cls);
}
-/*[clinic end generated code: output=e8d074b4e6437438 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=b41a400ef84f50af input=a9049054013a1b77]*/
diff --git a/Modules/clinic/arraymodule.c.h b/Modules/clinic/arraymodule.c.h
index 583ff28bf3287..030c6e7e1a487 100644
--- a/Modules/clinic/arraymodule.c.h
+++ b/Modules/clinic/arraymodule.c.h
@@ -155,13 +155,15 @@ array_array_extend(arrayobject *self, PyTypeObject *cls, PyObject *const *args,
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"", NULL};
- static _PyArg_Parser _parser = {"O:extend", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "extend", 0};
+ PyObject *argsbuf[1];
PyObject *bb;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &bb)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!args) {
goto exit;
}
+ bb = args[0];
return_value = array_array_extend_impl(self, cls, bb);
exit:
@@ -296,14 +298,28 @@ array_array_fromfile(arrayobject *self, PyTypeObject *cls, PyObject *const *args
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"", "", NULL};
- static _PyArg_Parser _parser = {"On:fromfile", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "fromfile", 0};
+ PyObject *argsbuf[2];
PyObject *f;
Py_ssize_t n;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &f, &n)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 2, 0, argsbuf);
+ if (!args) {
goto exit;
}
+ f = args[0];
+ {
+ Py_ssize_t ival = -1;
+ PyObject *iobj = _PyNumber_Index(args[1]);
+ if (iobj != NULL) {
+ ival = PyLong_AsSsize_t(iobj);
+ Py_DECREF(iobj);
+ }
+ if (ival == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ n = ival;
+ }
return_value = array_array_fromfile_impl(self, cls, f, n);
exit:
@@ -327,13 +343,15 @@ array_array_tofile(arrayobject *self, PyTypeObject *cls, PyObject *const *args,
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"", NULL};
- static _PyArg_Parser _parser = {"O:tofile", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "tofile", 0};
+ PyObject *argsbuf[1];
PyObject *f;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &f)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!args) {
goto exit;
}
+ f = args[0];
return_value = array_array_tofile_impl(self, cls, f);
exit:
@@ -567,13 +585,15 @@ array_array___reduce_ex__(arrayobject *self, PyTypeObject *cls, PyObject *const
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"", NULL};
- static _PyArg_Parser _parser = {"O:__reduce_ex__", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "__reduce_ex__", 0};
+ PyObject *argsbuf[1];
PyObject *value;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &value)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!args) {
goto exit;
}
+ value = args[0];
return_value = array_array___reduce_ex___impl(self, cls, value);
exit:
@@ -595,18 +615,11 @@ array_arrayiterator___reduce___impl(arrayiterobject *self, PyTypeObject *cls);
static PyObject *
array_arrayiterator___reduce__(arrayiterobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":__reduce__", _keywords, 0};
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
- goto exit;
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "__reduce__() takes no arguments");
+ return NULL;
}
- return_value = array_arrayiterator___reduce___impl(self, cls);
-
-exit:
- return return_value;
+ return array_arrayiterator___reduce___impl(self, cls);
}
PyDoc_STRVAR(array_arrayiterator___setstate____doc__,
@@ -617,4 +630,4 @@ PyDoc_STRVAR(array_arrayiterator___setstate____doc__,
#define ARRAY_ARRAYITERATOR___SETSTATE___METHODDEF \
{"__setstate__", (PyCFunction)array_arrayiterator___setstate__, METH_O, array_arrayiterator___setstate____doc__},
-/*[clinic end generated code: output=1db6decd8492bf91 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=7f48d1691fa27442 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/md5module.c.h b/Modules/clinic/md5module.c.h
index 4762f2800d4b8..0ff09b0050a56 100644
--- a/Modules/clinic/md5module.c.h
+++ b/Modules/clinic/md5module.c.h
@@ -17,18 +17,11 @@ MD5Type_copy_impl(MD5object *self, PyTypeObject *cls);
static PyObject *
MD5Type_copy(MD5object *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":copy", _keywords, 0};
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
- goto exit;
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "copy() takes no arguments");
+ return NULL;
}
- return_value = MD5Type_copy_impl(self, cls);
-
-exit:
- return return_value;
+ return MD5Type_copy_impl(self, cls);
}
PyDoc_STRVAR(MD5Type_digest__doc__,
@@ -126,4 +119,4 @@ _md5_md5(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kw
exit:
return return_value;
}
-/*[clinic end generated code: output=53ff7f22dbaaea36 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=3061297a669c645c input=a9049054013a1b77]*/
diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h
index 282a5410f7020..352dadc9b5627 100644
--- a/Modules/clinic/posixmodule.c.h
+++ b/Modules/clinic/posixmodule.c.h
@@ -8290,12 +8290,10 @@ static PyObject *
os_DirEntry_is_symlink(DirEntry *self, PyTypeObject *defining_class, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":is_symlink", _keywords, 0};
int _return_value;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "is_symlink() takes no arguments");
goto exit;
}
_return_value = os_DirEntry_is_symlink_impl(self, defining_class);
@@ -8326,13 +8324,23 @@ os_DirEntry_stat(DirEntry *self, PyTypeObject *defining_class, PyObject *const *
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"follow_symlinks", NULL};
- static _PyArg_Parser _parser = {"|$p:stat", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "stat", 0};
+ PyObject *argsbuf[1];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
int follow_symlinks = 1;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &follow_symlinks)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf);
+ if (!args) {
goto exit;
}
+ if (!noptargs) {
+ goto skip_optional_kwonly;
+ }
+ follow_symlinks = PyObject_IsTrue(args[0]);
+ if (follow_symlinks < 0) {
+ goto exit;
+ }
+skip_optional_kwonly:
return_value = os_DirEntry_stat_impl(self, defining_class, follow_symlinks);
exit:
@@ -8357,14 +8365,24 @@ os_DirEntry_is_dir(DirEntry *self, PyTypeObject *defining_class, PyObject *const
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"follow_symlinks", NULL};
- static _PyArg_Parser _parser = {"|$p:is_dir", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "is_dir", 0};
+ PyObject *argsbuf[1];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
int follow_symlinks = 1;
int _return_value;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &follow_symlinks)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf);
+ if (!args) {
goto exit;
}
+ if (!noptargs) {
+ goto skip_optional_kwonly;
+ }
+ follow_symlinks = PyObject_IsTrue(args[0]);
+ if (follow_symlinks < 0) {
+ goto exit;
+ }
+skip_optional_kwonly:
_return_value = os_DirEntry_is_dir_impl(self, defining_class, follow_symlinks);
if ((_return_value == -1) && PyErr_Occurred()) {
goto exit;
@@ -8393,14 +8411,24 @@ os_DirEntry_is_file(DirEntry *self, PyTypeObject *defining_class, PyObject *cons
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"follow_symlinks", NULL};
- static _PyArg_Parser _parser = {"|$p:is_file", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "is_file", 0};
+ PyObject *argsbuf[1];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 0;
int follow_symlinks = 1;
int _return_value;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &follow_symlinks)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 0, 0, argsbuf);
+ if (!args) {
goto exit;
}
+ if (!noptargs) {
+ goto skip_optional_kwonly;
+ }
+ follow_symlinks = PyObject_IsTrue(args[0]);
+ if (follow_symlinks < 0) {
+ goto exit;
+ }
+skip_optional_kwonly:
_return_value = os_DirEntry_is_file_impl(self, defining_class, follow_symlinks);
if ((_return_value == -1) && PyErr_Occurred()) {
goto exit;
@@ -9303,4 +9331,4 @@ os_waitstatus_to_exitcode(PyObject *module, PyObject *const *args, Py_ssize_t na
#ifndef OS_WAITSTATUS_TO_EXITCODE_METHODDEF
#define OS_WAITSTATUS_TO_EXITCODE_METHODDEF
#endif /* !defined(OS_WAITSTATUS_TO_EXITCODE_METHODDEF) */
-/*[clinic end generated code: output=d95ba7b0b9c52685 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=c8c5b148b96068b4 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/pyexpat.c.h b/Modules/clinic/pyexpat.c.h
index 7c56d6a8b2591..bee2ee66950a5 100644
--- a/Modules/clinic/pyexpat.c.h
+++ b/Modules/clinic/pyexpat.c.h
@@ -22,14 +22,24 @@ pyexpat_xmlparser_Parse(xmlparseobject *self, PyTypeObject *cls, PyObject *const
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"", "", NULL};
- static _PyArg_Parser _parser = {"O|i:Parse", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "Parse", 0};
+ PyObject *argsbuf[2];
PyObject *data;
int isfinal = 0;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &data, &isfinal)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ data = args[0];
+ if (nargs < 2) {
+ goto skip_optional_posonly;
+ }
+ isfinal = _PyLong_AsInt(args[1]);
+ if (isfinal == -1 && PyErr_Occurred()) {
goto exit;
}
+skip_optional_posonly:
return_value = pyexpat_xmlparser_Parse_impl(self, cls, data, isfinal);
exit:
@@ -54,13 +64,15 @@ pyexpat_xmlparser_ParseFile(xmlparseobject *self, PyTypeObject *cls, PyObject *c
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"", NULL};
- static _PyArg_Parser _parser = {"O:ParseFile", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "ParseFile", 0};
+ PyObject *argsbuf[1];
PyObject *file;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &file)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!args) {
goto exit;
}
+ file = args[0];
return_value = pyexpat_xmlparser_ParseFile_impl(self, cls, file);
exit:
@@ -164,14 +176,50 @@ pyexpat_xmlparser_ExternalEntityParserCreate(xmlparseobject *self, PyTypeObject
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"", "", NULL};
- static _PyArg_Parser _parser = {"z|s:ExternalEntityParserCreate", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "ExternalEntityParserCreate", 0};
+ PyObject *argsbuf[2];
const char *context;
const char *encoding = NULL;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &context, &encoding)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (args[0] == Py_None) {
+ context = NULL;
+ }
+ else if (PyUnicode_Check(args[0])) {
+ Py_ssize_t context_length;
+ context = PyUnicode_AsUTF8AndSize(args[0], &context_length);
+ if (context == NULL) {
+ goto exit;
+ }
+ if (strlen(context) != (size_t)context_length) {
+ PyErr_SetString(PyExc_ValueError, "embedded null character");
+ goto exit;
+ }
+ }
+ else {
+ _PyArg_BadArgument("ExternalEntityParserCreate", "argument 1", "str or None", args[0]);
+ goto exit;
+ }
+ if (nargs < 2) {
+ goto skip_optional_posonly;
+ }
+ if (!PyUnicode_Check(args[1])) {
+ _PyArg_BadArgument("ExternalEntityParserCreate", "argument 2", "str", args[1]);
goto exit;
}
+ Py_ssize_t encoding_length;
+ encoding = PyUnicode_AsUTF8AndSize(args[1], &encoding_length);
+ if (encoding == NULL) {
+ goto exit;
+ }
+ if (strlen(encoding) != (size_t)encoding_length) {
+ PyErr_SetString(PyExc_ValueError, "embedded null character");
+ goto exit;
+ }
+skip_optional_posonly:
return_value = pyexpat_xmlparser_ExternalEntityParserCreate_impl(self, cls, context, encoding);
exit:
@@ -235,13 +283,22 @@ pyexpat_xmlparser_UseForeignDTD(xmlparseobject *self, PyTypeObject *cls, PyObjec
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"", NULL};
- static _PyArg_Parser _parser = {"|p:UseForeignDTD", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "UseForeignDTD", 0};
+ PyObject *argsbuf[1];
int flag = 1;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &flag)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (nargs < 1) {
+ goto skip_optional_posonly;
+ }
+ flag = PyObject_IsTrue(args[0]);
+ if (flag < 0) {
goto exit;
}
+skip_optional_posonly:
return_value = pyexpat_xmlparser_UseForeignDTD_impl(self, cls, flag);
exit:
@@ -368,4 +425,4 @@ pyexpat_ErrorString(PyObject *module, PyObject *arg)
#ifndef PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF
#define PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF
#endif /* !defined(PYEXPAT_XMLPARSER_USEFOREIGNDTD_METHODDEF) */
-/*[clinic end generated code: output=612b9d6a17a679a7 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=5d60049d385d5d56 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/sha1module.c.h b/Modules/clinic/sha1module.c.h
index 3a3ab58c1233c..d9a2e150f6d41 100644
--- a/Modules/clinic/sha1module.c.h
+++ b/Modules/clinic/sha1module.c.h
@@ -17,18 +17,11 @@ SHA1Type_copy_impl(SHA1object *self, PyTypeObject *cls);
static PyObject *
SHA1Type_copy(SHA1object *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":copy", _keywords, 0};
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
- goto exit;
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "copy() takes no arguments");
+ return NULL;
}
- return_value = SHA1Type_copy_impl(self, cls);
-
-exit:
- return return_value;
+ return SHA1Type_copy_impl(self, cls);
}
PyDoc_STRVAR(SHA1Type_digest__doc__,
@@ -126,4 +119,4 @@ _sha1_sha1(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *
exit:
return return_value;
}
-/*[clinic end generated code: output=abf1ab2545cea5a2 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=93ced3c8f8fa4f21 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/sha256module.c.h b/Modules/clinic/sha256module.c.h
index 89205c4f14f4e..619fab1a6fe2f 100644
--- a/Modules/clinic/sha256module.c.h
+++ b/Modules/clinic/sha256module.c.h
@@ -17,18 +17,11 @@ SHA256Type_copy_impl(SHAobject *self, PyTypeObject *cls);
static PyObject *
SHA256Type_copy(SHAobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":copy", _keywords, 0};
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
- goto exit;
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "copy() takes no arguments");
+ return NULL;
}
- return_value = SHA256Type_copy_impl(self, cls);
-
-exit:
- return return_value;
+ return SHA256Type_copy_impl(self, cls);
}
PyDoc_STRVAR(SHA256Type_digest__doc__,
@@ -177,4 +170,4 @@ _sha256_sha224(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje
exit:
return return_value;
}
-/*[clinic end generated code: output=b7283f75c9d08f30 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=4f9fe3ca546b0c58 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/sha512module.c.h b/Modules/clinic/sha512module.c.h
index f1192d74f9a1a..fada35eff2261 100644
--- a/Modules/clinic/sha512module.c.h
+++ b/Modules/clinic/sha512module.c.h
@@ -17,18 +17,11 @@ SHA512Type_copy_impl(SHAobject *self, PyTypeObject *cls);
static PyObject *
SHA512Type_copy(SHAobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":copy", _keywords, 0};
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
- goto exit;
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "copy() takes no arguments");
+ return NULL;
}
- return_value = SHA512Type_copy_impl(self, cls);
-
-exit:
- return return_value;
+ return SHA512Type_copy_impl(self, cls);
}
PyDoc_STRVAR(SHA512Type_digest__doc__,
@@ -177,4 +170,4 @@ _sha512_sha384(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje
exit:
return return_value;
}
-/*[clinic end generated code: output=9ff9f11937fabf35 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=26d2fe27b9673ac2 input=a9049054013a1b77]*/
diff --git a/Modules/clinic/zlibmodule.c.h b/Modules/clinic/zlibmodule.c.h
index 71136d31db0e0..deadf872d0cf7 100644
--- a/Modules/clinic/zlibmodule.c.h
+++ b/Modules/clinic/zlibmodule.c.h
@@ -352,11 +352,19 @@ zlib_Compress_compress(compobject *self, PyTypeObject *cls, PyObject *const *arg
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"", NULL};
- static _PyArg_Parser _parser = {"y*:compress", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "compress", 0};
+ PyObject *argsbuf[1];
Py_buffer data = {NULL, NULL};
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &data)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) {
+ goto exit;
+ }
+ if (!PyBuffer_IsContiguous(&data, 'C')) {
+ _PyArg_BadArgument("compress", "argument 1", "contiguous buffer", args[0]);
goto exit;
}
return_value = zlib_Compress_compress_impl(self, cls, &data);
@@ -399,14 +407,39 @@ zlib_Decompress_decompress(compobject *self, PyTypeObject *cls, PyObject *const
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"", "max_length", NULL};
- static _PyArg_Parser _parser = {"y*|n:decompress", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "decompress", 0};
+ PyObject *argsbuf[2];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
Py_buffer data = {NULL, NULL};
Py_ssize_t max_length = 0;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &data, &max_length)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 2, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (PyObject_GetBuffer(args[0], &data, PyBUF_SIMPLE) != 0) {
+ goto exit;
+ }
+ if (!PyBuffer_IsContiguous(&data, 'C')) {
+ _PyArg_BadArgument("decompress", "argument 1", "contiguous buffer", args[0]);
goto exit;
}
+ if (!noptargs) {
+ goto skip_optional_pos;
+ }
+ {
+ Py_ssize_t ival = -1;
+ PyObject *iobj = _PyNumber_Index(args[1]);
+ if (iobj != NULL) {
+ ival = PyLong_AsSsize_t(iobj);
+ Py_DECREF(iobj);
+ }
+ if (ival == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ max_length = ival;
+ }
+skip_optional_pos:
return_value = zlib_Decompress_decompress_impl(self, cls, &data, max_length);
exit:
@@ -441,13 +474,22 @@ zlib_Compress_flush(compobject *self, PyTypeObject *cls, PyObject *const *args,
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"", NULL};
- static _PyArg_Parser _parser = {"|i:flush", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "flush", 0};
+ PyObject *argsbuf[1];
int mode = Z_FINISH;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &mode)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (nargs < 1) {
+ goto skip_optional_posonly;
+ }
+ mode = _PyLong_AsInt(args[0]);
+ if (mode == -1 && PyErr_Occurred()) {
goto exit;
}
+skip_optional_posonly:
return_value = zlib_Compress_flush_impl(self, cls, mode);
exit:
@@ -471,18 +513,11 @@ zlib_Compress_copy_impl(compobject *self, PyTypeObject *cls);
static PyObject *
zlib_Compress_copy(compobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":copy", _keywords, 0};
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
- goto exit;
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "copy() takes no arguments");
+ return NULL;
}
- return_value = zlib_Compress_copy_impl(self, cls);
-
-exit:
- return return_value;
+ return zlib_Compress_copy_impl(self, cls);
}
#endif /* defined(HAVE_ZLIB_COPY) */
@@ -503,18 +538,11 @@ zlib_Compress___copy___impl(compobject *self, PyTypeObject *cls);
static PyObject *
zlib_Compress___copy__(compobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":__copy__", _keywords, 0};
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
- goto exit;
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "__copy__() takes no arguments");
+ return NULL;
}
- return_value = zlib_Compress___copy___impl(self, cls);
-
-exit:
- return return_value;
+ return zlib_Compress___copy___impl(self, cls);
}
#endif /* defined(HAVE_ZLIB_COPY) */
@@ -538,13 +566,15 @@ zlib_Compress___deepcopy__(compobject *self, PyTypeObject *cls, PyObject *const
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"", NULL};
- static _PyArg_Parser _parser = {"O:__deepcopy__", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "__deepcopy__", 0};
+ PyObject *argsbuf[1];
PyObject *memo;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &memo)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!args) {
goto exit;
}
+ memo = args[0];
return_value = zlib_Compress___deepcopy___impl(self, cls, memo);
exit:
@@ -570,18 +600,11 @@ zlib_Decompress_copy_impl(compobject *self, PyTypeObject *cls);
static PyObject *
zlib_Decompress_copy(compobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":copy", _keywords, 0};
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
- goto exit;
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "copy() takes no arguments");
+ return NULL;
}
- return_value = zlib_Decompress_copy_impl(self, cls);
-
-exit:
- return return_value;
+ return zlib_Decompress_copy_impl(self, cls);
}
#endif /* defined(HAVE_ZLIB_COPY) */
@@ -602,18 +625,11 @@ zlib_Decompress___copy___impl(compobject *self, PyTypeObject *cls);
static PyObject *
zlib_Decompress___copy__(compobject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *return_value = NULL;
- static const char * const _keywords[] = { NULL};
- static _PyArg_Parser _parser = {":__copy__", _keywords, 0};
-
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser
- )) {
- goto exit;
+ if (nargs) {
+ PyErr_SetString(PyExc_TypeError, "__copy__() takes no arguments");
+ return NULL;
}
- return_value = zlib_Decompress___copy___impl(self, cls);
-
-exit:
- return return_value;
+ return zlib_Decompress___copy___impl(self, cls);
}
#endif /* defined(HAVE_ZLIB_COPY) */
@@ -637,13 +653,15 @@ zlib_Decompress___deepcopy__(compobject *self, PyTypeObject *cls, PyObject *cons
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"", NULL};
- static _PyArg_Parser _parser = {"O:__deepcopy__", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "__deepcopy__", 0};
+ PyObject *argsbuf[1];
PyObject *memo;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &memo)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
+ if (!args) {
goto exit;
}
+ memo = args[0];
return_value = zlib_Decompress___deepcopy___impl(self, cls, memo);
exit:
@@ -673,13 +691,30 @@ zlib_Decompress_flush(compobject *self, PyTypeObject *cls, PyObject *const *args
{
PyObject *return_value = NULL;
static const char * const _keywords[] = {"", NULL};
- static _PyArg_Parser _parser = {"|n:flush", _keywords, 0};
+ static _PyArg_Parser _parser = {NULL, _keywords, "flush", 0};
+ PyObject *argsbuf[1];
Py_ssize_t length = DEF_BUF_SIZE;
- if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
- &length)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 0, 1, 0, argsbuf);
+ if (!args) {
goto exit;
}
+ if (nargs < 1) {
+ goto skip_optional_posonly;
+ }
+ {
+ Py_ssize_t ival = -1;
+ PyObject *iobj = _PyNumber_Index(args[0]);
+ if (iobj != NULL) {
+ ival = PyLong_AsSsize_t(iobj);
+ Py_DECREF(iobj);
+ }
+ if (ival == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ length = ival;
+ }
+skip_optional_posonly:
return_value = zlib_Decompress_flush_impl(self, cls, length);
exit:
@@ -820,4 +855,4 @@ zlib_crc32(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
#ifndef ZLIB_DECOMPRESS___DEEPCOPY___METHODDEF
#define ZLIB_DECOMPRESS___DEEPCOPY___METHODDEF
#endif /* !defined(ZLIB_DECOMPRESS___DEEPCOPY___METHODDEF) */
-/*[clinic end generated code: output=f009d194565416d1 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=bb1e27d8b2198a86 input=a9049054013a1b77]*/
diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.py
index 14252b2514ea8..f660474da94a0 100755
--- a/Tools/clinic/clinic.py
+++ b/Tools/clinic/clinic.py
@@ -639,6 +639,10 @@ def output_templates(self, f):
assert parameters
assert isinstance(parameters[0].converter, self_converter)
del parameters[0]
+ requires_defining_class = False
+ if parameters and isinstance(parameters[0].converter, defining_class_converter):
+ requires_defining_class = True
+ del parameters[0]
converters = [p.converter for p in parameters]
has_option_groups = parameters and (parameters[0].group or parameters[-1].group)
@@ -667,10 +671,6 @@ def output_templates(self, f):
if not p.is_optional():
min_pos = i
- requires_defining_class = any(
- isinstance(p.converter, defining_class_converter)
- for p in parameters)
-
meth_o = (len(parameters) == 1 and
parameters[0].is_positional_only() and
not converters[0].is_optional() and
@@ -773,24 +773,40 @@ def parser_body(prototype, *fields, declarations=''):
return linear_format(output(), parser_declarations=declarations)
if not parameters:
- # no parameters, METH_NOARGS
+ if not requires_defining_class:
+ # no parameters, METH_NOARGS
+ flags = "METH_NOARGS"
- flags = "METH_NOARGS"
+ parser_prototype = normalize_snippet("""
+ static PyObject *
+ {c_basename}({self_type}{self_name}, PyObject *Py_UNUSED(ignored))
+ """)
+ parser_code = []
- parser_prototype = normalize_snippet("""
- static PyObject *
- {c_basename}({self_type}{self_name}, PyObject *Py_UNUSED(ignored))
- """)
- parser_definition = parser_prototype
+ else:
+ assert not new_or_init
- if default_return_converter:
- parser_definition = parser_prototype + '\n' + normalize_snippet("""
- {{
- return {c_basename}_impl({impl_arguments});
+ flags = "METH_METHOD|METH_FASTCALL|METH_KEYWORDS"
+
+ parser_prototype = parser_prototype_def_class
+ return_error = ('return NULL;' if default_return_converter
+ else 'goto exit;')
+ parser_code = [normalize_snippet("""
+ if (nargs) {{
+ PyErr_SetString(PyExc_TypeError, "{name}() takes no arguments");
+ %s
}}
- """)
+ """ % return_error, indent=4)]
+
+ if default_return_converter:
+ parser_definition = '\n'.join([
+ parser_prototype,
+ '{{',
+ *parser_code,
+ ' return {c_basename}_impl({impl_arguments});',
+ '}}'])
else:
- parser_definition = parser_body(parser_prototype)
+ parser_definition = parser_body(parser_prototype, *parser_code)
elif meth_o:
flags = "METH_O"
@@ -993,6 +1009,9 @@ def parser_body(prototype, *fields, declarations=''):
add_label = None
for i, p in enumerate(parameters):
+ if isinstance(p.converter, defining_class_converter):
+ raise ValueError("defining_class should be the first "
+ "parameter (after self)")
displayname = p.get_displayname(i+1)
parsearg = p.converter.parse_arg(argname_fmt % i, displayname)
if parsearg is None:
1
0
gh-91760: Deprecate group names and numbers which will be invalid in future (GH-91794)
by serhiy-storchaka April 30, 2022
by serhiy-storchaka April 30, 2022
April 30, 2022
https://github.com/python/cpython/commit/19dca041212f9f58ee11833bff3f8c157d…
commit: 19dca041212f9f58ee11833bff3f8c157d4fd3e8
branch: main
author: Serhiy Storchaka <storchaka(a)gmail.com>
committer: serhiy-storchaka <storchaka(a)gmail.com>
date: 2022-04-30T13:13:46+03:00
summary:
gh-91760: Deprecate group names and numbers which will be invalid in future (GH-91794)
Only sequence of ASCII digits will be accepted as a numerical reference.
The group name in bytes patterns and replacement strings could only
contain ASCII letters and digits and underscore.
files:
A Misc/NEWS.d/next/Library/2022-04-21-19-46-03.gh-issue-91760.zDtv1E.rst
M Doc/library/re.rst
M Doc/whatsnew/3.11.rst
M Lib/re/_parser.py
M Lib/test/test_re.py
diff --git a/Doc/library/re.rst b/Doc/library/re.rst
index 89de9286ace79..3cd9f252fee6f 100644
--- a/Doc/library/re.rst
+++ b/Doc/library/re.rst
@@ -417,6 +417,9 @@ The special characters are:
| | * ``\1`` |
+---------------------------------------+----------------------------------+
+ .. deprecated:: 3.11
+ Group names containing non-ASCII characters in bytes patterns.
+
.. index:: single: (?P=; in regular expressions
``(?P=name)``
@@ -486,6 +489,9 @@ The special characters are:
will match with ``'<user(a)host.com>'`` as well as ``'user(a)host.com'``, but
not with ``'<user(a)host.com'`` nor ``'user(a)host.com>'``.
+ .. deprecated:: 3.11
+ Group *id* containing anything except ASCII digits.
+
The special sequences consist of ``'\'`` and a character from the list below.
If the ordinary character is not an ASCII digit or an ASCII letter, then the
@@ -995,6 +1001,10 @@ form.
Empty matches for the pattern are replaced when adjacent to a previous
non-empty match.
+ .. deprecated:: 3.11
+ Group *id* containing anything except ASCII digits.
+ Group names containing non-ASCII characters in bytes replacement strings.
+
.. function:: subn(pattern, repl, string, count=0, flags=0)
diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst
index fdd35ce14317e..1a692f2fe7f60 100644
--- a/Doc/whatsnew/3.11.rst
+++ b/Doc/whatsnew/3.11.rst
@@ -1151,6 +1151,14 @@ Deprecated
(Contributed by Brett Cannon in :issue:`47061` and Victor Stinner in
:gh:`68966`.)
+* More strict rules will be applied now applied for numerical group references
+ and group names in regular expressions in future Python versions.
+ Only sequence of ASCII digits will be now accepted as a numerical reference.
+ The group name in bytes patterns and replacement strings could only
+ contain ASCII letters and digits and underscore.
+ For now, a deprecation warning is raised for such syntax.
+ (Contributed by Serhiy Storchaka in :gh:`91760`.)
+
Removed
=======
diff --git a/Lib/re/_parser.py b/Lib/re/_parser.py
index 933d51589f46c..a393c508d86e5 100644
--- a/Lib/re/_parser.py
+++ b/Lib/re/_parser.py
@@ -287,8 +287,22 @@ def seek(self, index):
self.__next()
def error(self, msg, offset=0):
+ if not self.istext:
+ msg = msg.encode('ascii', 'backslashreplace').decode('ascii')
return error(msg, self.string, self.tell() - offset)
+ def checkgroupname(self, name, offset, nested):
+ if not name.isidentifier():
+ msg = "bad character in group name %r" % name
+ raise self.error(msg, len(name) + offset)
+ if not (self.istext or name.isascii()):
+ import warnings
+ warnings.warn(
+ "bad character in group name %a at position %d" %
+ (name, self.tell() - len(name) - offset),
+ DeprecationWarning, stacklevel=nested + 7
+ )
+
def _class_escape(source, escape):
# handle escape code inside character class
code = ESCAPES.get(escape)
@@ -703,15 +717,11 @@ def _parse(source, state, verbose, nested, first=False):
if sourcematch("<"):
# named group: skip forward to end of name
name = source.getuntil(">", "group name")
- if not name.isidentifier():
- msg = "bad character in group name %r" % name
- raise source.error(msg, len(name) + 1)
+ source.checkgroupname(name, 1, nested)
elif sourcematch("="):
# named backreference
name = source.getuntil(")", "group name")
- if not name.isidentifier():
- msg = "bad character in group name %r" % name
- raise source.error(msg, len(name) + 1)
+ source.checkgroupname(name, 1, nested)
gid = state.groupdict.get(name)
if gid is None:
msg = "unknown group name %r" % name
@@ -773,6 +783,7 @@ def _parse(source, state, verbose, nested, first=False):
# conditional backreference group
condname = source.getuntil(")", "group name")
if condname.isidentifier():
+ source.checkgroupname(condname, 1, nested)
condgroup = state.groupdict.get(condname)
if condgroup is None:
msg = "unknown group name %r" % condname
@@ -795,6 +806,14 @@ def _parse(source, state, verbose, nested, first=False):
state.grouprefpos[condgroup] = (
source.tell() - len(condname) - 1
)
+ if not (condname.isdecimal() and condname.isascii()):
+ import warnings
+ warnings.warn(
+ "bad character in group name %s at position %d" %
+ (repr(condname) if source.istext else ascii(condname),
+ source.tell() - len(condname) - 1),
+ DeprecationWarning, stacklevel=nested + 6
+ )
state.checklookbehindgroup(condgroup, source)
item_yes = _parse(source, state, verbose, nested + 1)
if source.match("|"):
@@ -1000,11 +1019,11 @@ def addgroup(index, pos):
# group
c = this[1]
if c == "g":
- name = ""
if not s.match("<"):
raise s.error("missing <")
name = s.getuntil(">", "group name")
if name.isidentifier():
+ s.checkgroupname(name, 1, -1)
try:
index = groupindex[name]
except KeyError:
@@ -1020,6 +1039,14 @@ def addgroup(index, pos):
if index >= MAXGROUPS:
raise s.error("invalid group reference %d" % index,
len(name) + 1)
+ if not (name.isdecimal() and name.isascii()):
+ import warnings
+ warnings.warn(
+ "bad character in group name %s at position %d" %
+ (repr(name) if s.istext else ascii(name),
+ s.tell() - len(name) - 1),
+ DeprecationWarning, stacklevel=5
+ )
addgroup(index, len(name) + 1)
elif c == "0":
if s.next in OCTDIGITS:
diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py
index a4c2f1f3e4ba3..c1014753802c9 100644
--- a/Lib/test/test_re.py
+++ b/Lib/test/test_re.py
@@ -135,6 +135,7 @@ def test_basic_re_sub(self):
self.assertEqual(re.sub('(?P<a>x)', r'\g<a>\g<1>', 'xx'), 'xxxx')
self.assertEqual(re.sub('(?P<unk>x)', r'\g<unk>\g<unk>', 'xx'), 'xxxx')
self.assertEqual(re.sub('(?P<unk>x)', r'\g<1>\g<1>', 'xx'), 'xxxx')
+ self.assertEqual(re.sub('()x', r'\g<0>\g<0>', 'xx'), 'xxxx')
self.assertEqual(re.sub('a', r'\t\n\v\r\f\a\b', 'a'), '\t\n\v\r\f\a\b')
self.assertEqual(re.sub('a', '\t\n\v\r\f\a\b', 'a'), '\t\n\v\r\f\a\b')
@@ -274,6 +275,21 @@ def test_symbolic_groups_errors(self):
self.checkPatternError('(?P<©>x)', "bad character in group name '©'", 4)
self.checkPatternError('(?P=©)', "bad character in group name '©'", 4)
self.checkPatternError('(?(©)y)', "bad character in group name '©'", 3)
+ with self.assertWarnsRegex(DeprecationWarning,
+ r"bad character in group name '\\xc2\\xb5' "
+ r"at position 4") as w:
+ re.compile(b'(?P<\xc2\xb5>x)')
+ self.assertEqual(w.filename, __file__)
+ with self.assertWarnsRegex(DeprecationWarning,
+ r"bad character in group name '\\xc2\\xb5' "
+ r"at position 4"):
+ self.checkPatternError(b'(?P=\xc2\xb5)',
+ r"unknown group name '\xc2\xb5'", 4)
+ with self.assertWarnsRegex(DeprecationWarning,
+ r"bad character in group name '\\xc2\\xb5' "
+ r"at position 3"):
+ self.checkPatternError(b'(?(\xc2\xb5)y)',
+ r"unknown group name '\xc2\xb5'", 3)
def test_symbolic_refs(self):
self.assertEqual(re.sub('(?P<a>x)|(?P<b>y)', r'\g<b>', 'xx'), '')
@@ -306,12 +322,35 @@ def test_symbolic_refs_errors(self):
re.sub('(?P<a>x)', r'\g<ab>', 'xx')
self.checkTemplateError('(?P<a>x)', r'\g<-1>', 'xx',
"bad character in group name '-1'", 3)
+ with self.assertWarnsRegex(DeprecationWarning,
+ r"bad character in group name '\+1' "
+ r"at position 3") as w:
+ re.sub('(?P<a>x)', r'\g<+1>', 'xx')
+ self.assertEqual(w.filename, __file__)
+ with self.assertWarnsRegex(DeprecationWarning,
+ r"bad character in group name '1_0' "
+ r"at position 3"):
+ re.sub('()'*10, r'\g<1_0>', 'xx')
+ with self.assertWarnsRegex(DeprecationWarning,
+ r"bad character in group name ' 1 ' "
+ r"at position 3"):
+ re.sub('(?P<a>x)', r'\g< 1 >', 'xx')
self.checkTemplateError('(?P<a>x)', r'\g<©>', 'xx',
"bad character in group name '©'", 3)
+ with self.assertWarnsRegex(DeprecationWarning,
+ r"bad character in group name '\\xc2\\xb5' "
+ r"at position 3") as w:
+ with self.assertRaisesRegex(IndexError, "unknown group name '\xc2\xb5'"):
+ re.sub(b'(?P<a>x)', b'\\g<\xc2\xb5>', b'xx')
+ self.assertEqual(w.filename, __file__)
self.checkTemplateError('(?P<a>x)', r'\g<㊀>', 'xx',
"bad character in group name '㊀'", 3)
self.checkTemplateError('(?P<a>x)', r'\g<¹>', 'xx',
"bad character in group name '¹'", 3)
+ with self.assertWarnsRegex(DeprecationWarning,
+ r"bad character in group name '१' "
+ r"at position 3"):
+ re.sub('(?P<a>x)', r'\g<१>', 'xx')
def test_re_subn(self):
self.assertEqual(re.subn("(?i)b+", "x", "bbbb BBBB"), ('x x', 2))
@@ -577,10 +616,27 @@ def test_re_groupref_exists_errors(self):
self.checkPatternError(r'(?P<a>)(?(0)a|b)', 'bad group number', 10)
self.checkPatternError(r'()(?(-1)a|b)',
"bad character in group name '-1'", 5)
+ with self.assertWarnsRegex(DeprecationWarning,
+ r"bad character in group name '\+1' "
+ r"at position 5") as w:
+ re.compile(r'()(?(+1)a|b)')
+ self.assertEqual(w.filename, __file__)
+ with self.assertWarnsRegex(DeprecationWarning,
+ r"bad character in group name '1_0' "
+ r"at position 23"):
+ re.compile(r'()'*10 + r'(?(1_0)a|b)')
+ with self.assertWarnsRegex(DeprecationWarning,
+ r"bad character in group name ' 1 ' "
+ r"at position 5"):
+ re.compile(r'()(?( 1 )a|b)')
self.checkPatternError(r'()(?(㊀)a|b)',
"bad character in group name '㊀'", 5)
self.checkPatternError(r'()(?(¹)a|b)',
"bad character in group name '¹'", 5)
+ with self.assertWarnsRegex(DeprecationWarning,
+ r"bad character in group name '१' "
+ r"at position 5"):
+ re.compile(r'()(?(१)a|b)')
self.checkPatternError(r'()(?(1',
"missing ), unterminated name", 5)
self.checkPatternError(r'()(?(1)a',
diff --git a/Misc/NEWS.d/next/Library/2022-04-21-19-46-03.gh-issue-91760.zDtv1E.rst b/Misc/NEWS.d/next/Library/2022-04-21-19-46-03.gh-issue-91760.zDtv1E.rst
new file mode 100644
index 0000000000000..0bddbbe093144
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-04-21-19-46-03.gh-issue-91760.zDtv1E.rst
@@ -0,0 +1,4 @@
+More strict rules will be applied for numerical group references and group
+names in regular expressions. For now, a deprecation warning is emitted for
+group references and group names which will be errors in future Python
+versions.
1
0
gh-92049: Forbid pickling constants re._constants.SUCCESS etc (GH-92070)
by serhiy-storchaka April 30, 2022
by serhiy-storchaka April 30, 2022
April 30, 2022
https://github.com/python/cpython/commit/6d0d547033e295f91f05030322acfbb0e2…
commit: 6d0d547033e295f91f05030322acfbb0e280fc1f
branch: main
author: Serhiy Storchaka <storchaka(a)gmail.com>
committer: serhiy-storchaka <storchaka(a)gmail.com>
date: 2022-04-30T13:03:23+03:00
summary:
gh-92049: Forbid pickling constants re._constants.SUCCESS etc (GH-92070)
Previously, pickling did not fail, but the result could not be unpickled.
files:
A Misc/NEWS.d/next/Library/2022-04-30-10-53-10.gh-issue-92049.5SEKoh.rst
M Lib/re/_constants.py
diff --git a/Lib/re/_constants.py b/Lib/re/_constants.py
index c45ce409e21b8..71204d903b322 100644
--- a/Lib/re/_constants.py
+++ b/Lib/re/_constants.py
@@ -62,6 +62,8 @@ def __new__(cls, value, name):
def __repr__(self):
return self.name
+ __reduce__ = None
+
MAXREPEAT = _NamedIntConstant(MAXREPEAT, 'MAXREPEAT')
def _makecodes(*names):
diff --git a/Misc/NEWS.d/next/Library/2022-04-30-10-53-10.gh-issue-92049.5SEKoh.rst b/Misc/NEWS.d/next/Library/2022-04-30-10-53-10.gh-issue-92049.5SEKoh.rst
new file mode 100644
index 0000000000000..cad4621c65096
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-04-30-10-53-10.gh-issue-92049.5SEKoh.rst
@@ -0,0 +1,2 @@
+Forbid pickling constants ``re._constants.SUCCESS`` etc. Previously,
+pickling did not fail, but the result could not be unpickled.
1
0
April 30, 2022
https://github.com/python/cpython/commit/354ace8b07e7d445fd2de713b6af127153…
commit: 354ace8b07e7d445fd2de713b6af1271536adce0
branch: main
author: Inada Naoki <songofacandy(a)gmail.com>
committer: methane <songofacandy(a)gmail.com>
date: 2022-04-30T15:53:29+09:00
summary:
gh-91954: Emit EncodingWarning from locale and subprocess (GH-91977)
locale.getpreferredencoding() and subprocess.Popen() emit EncodingWarning
files:
A Misc/NEWS.d/next/Library/2022-04-27-13-30-26.gh-issue-91954.cC7ga_.rst
M Doc/library/subprocess.rst
M Lib/locale.py
M Lib/subprocess.py
M Lib/test/test_subprocess.py
diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst
index fca5549649268..6a334acc5a17c 100644
--- a/Doc/library/subprocess.rst
+++ b/Doc/library/subprocess.rst
@@ -619,7 +619,7 @@ functions.
If *encoding* or *errors* are specified, or *text* is true, the file objects
*stdin*, *stdout* and *stderr* are opened in text mode with the specified
- encoding and *errors*, as described above in :ref:`frequently-used-arguments`.
+ *encoding* and *errors*, as described above in :ref:`frequently-used-arguments`.
The *universal_newlines* argument is equivalent to *text* and is provided
for backwards compatibility. By default, file objects are opened in binary mode.
@@ -1445,12 +1445,13 @@ This module also provides the following legacy functions from the 2.x
none of the guarantees described above regarding security and exception
handling consistency are valid for these functions.
-.. function:: getstatusoutput(cmd)
+.. function:: getstatusoutput(cmd, *, encoding=None, errors=None)
Return ``(exitcode, output)`` of executing *cmd* in a shell.
Execute the string *cmd* in a shell with :meth:`Popen.check_output` and
- return a 2-tuple ``(exitcode, output)``. The locale encoding is used;
+ return a 2-tuple ``(exitcode, output)``.
+ *encoding* and *errors* are used to decode output;
see the notes on :ref:`frequently-used-arguments` for more details.
A trailing newline is stripped from the output.
@@ -1475,8 +1476,10 @@ handling consistency are valid for these functions.
as it did in Python 3.3.3 and earlier. exitcode has the same value as
:attr:`~Popen.returncode`.
+ .. versionadded:: 3.11
+ Added *encoding* and *errors* arguments.
-.. function:: getoutput(cmd)
+.. function:: getoutput(cmd, *, encoding=None, errors=None)
Return output (stdout and stderr) of executing *cmd* in a shell.
@@ -1491,6 +1494,9 @@ handling consistency are valid for these functions.
.. versionchanged:: 3.3.4
Windows support added
+ .. versionadded:: 3.11
+ Added *encoding* and *errors* arguments.
+
Notes
-----
diff --git a/Lib/locale.py b/Lib/locale.py
index 170e5eea45b8c..25eb75ac65a32 100644
--- a/Lib/locale.py
+++ b/Lib/locale.py
@@ -655,6 +655,11 @@ def getencoding():
except NameError:
def getpreferredencoding(do_setlocale=True):
"""Return the charset that the user is likely using."""
+ if sys.flags.warn_default_encoding:
+ import warnings
+ warnings.warn(
+ "UTF-8 Mode affects locale.getpreferredencoding(). Consider locale.getencoding() instead.",
+ EncodingWarning, 2)
if sys.flags.utf8_mode:
return 'utf-8'
return getencoding()
@@ -663,6 +668,12 @@ def getpreferredencoding(do_setlocale=True):
def getpreferredencoding(do_setlocale=True):
"""Return the charset that the user is likely using,
according to the system configuration."""
+
+ if sys.flags.warn_default_encoding:
+ import warnings
+ warnings.warn(
+ "UTF-8 Mode affects locale.getpreferredencoding(). Consider locale.getencoding() instead.",
+ EncodingWarning, 2)
if sys.flags.utf8_mode:
return 'utf-8'
diff --git a/Lib/subprocess.py b/Lib/subprocess.py
index a5fa152715c14..968cfc14ddf91 100644
--- a/Lib/subprocess.py
+++ b/Lib/subprocess.py
@@ -43,6 +43,7 @@
import builtins
import errno
import io
+import locale
import os
import time
import signal
@@ -344,6 +345,26 @@ def _args_from_interpreter_flags():
return args
+def _text_encoding():
+ # Return default text encoding and emit EncodingWarning if
+ # sys.flags.warn_default_encoding is true.
+ if sys.flags.warn_default_encoding:
+ f = sys._getframe()
+ filename = f.f_code.co_filename
+ stacklevel = 2
+ while f := f.f_back:
+ if f.f_code.co_filename != filename:
+ break
+ stacklevel += 1
+ warnings.warn("'encoding' argument not specified.",
+ EncodingWarning, stacklevel)
+
+ if sys.flags.utf8_mode:
+ return "utf-8"
+ else:
+ return locale.getencoding()
+
+
def call(*popenargs, timeout=None, **kwargs):
"""Run command with arguments. Wait for command to complete or
timeout, then return the returncode attribute.
@@ -610,7 +631,7 @@ def list2cmdline(seq):
# Various tools for executing commands and looking at their output and status.
#
-def getstatusoutput(cmd):
+def getstatusoutput(cmd, *, encoding=None, errors=None):
"""Return (exitcode, output) of executing cmd in a shell.
Execute the string 'cmd' in a shell with 'check_output' and
@@ -632,7 +653,8 @@ def getstatusoutput(cmd):
(-15, '')
"""
try:
- data = check_output(cmd, shell=True, text=True, stderr=STDOUT)
+ data = check_output(cmd, shell=True, text=True, stderr=STDOUT,
+ encoding=encoding, errors=errors)
exitcode = 0
except CalledProcessError as ex:
data = ex.output
@@ -641,7 +663,7 @@ def getstatusoutput(cmd):
data = data[:-1]
return exitcode, data
-def getoutput(cmd):
+def getoutput(cmd, *, encoding=None, errors=None):
"""Return output (stdout or stderr) of executing cmd in a shell.
Like getstatusoutput(), except the exit status is ignored and the return
@@ -651,7 +673,8 @@ def getoutput(cmd):
>>> subprocess.getoutput('ls /bin/ls')
'/bin/ls'
"""
- return getstatusoutput(cmd)[1]
+ return getstatusoutput(cmd, encoding=encoding, errors=errors)[1]
+
def _use_posix_spawn():
@@ -858,13 +881,8 @@ def __init__(self, args, bufsize=-1, executable=None,
errread = msvcrt.open_osfhandle(errread.Detach(), 0)
self.text_mode = encoding or errors or text or universal_newlines
-
- # PEP 597: We suppress the EncodingWarning in subprocess module
- # for now (at Python 3.10), because we focus on files for now.
- # This will be changed to encoding = io.text_encoding(encoding)
- # in the future.
if self.text_mode and encoding is None:
- self.encoding = encoding = "locale"
+ self.encoding = encoding = _text_encoding()
# How long to resume waiting on a child after the first ^C.
# There is no right value for this. The purpose is to be polite
diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py
index 99b5947e54be6..5814a6d924e12 100644
--- a/Lib/test/test_subprocess.py
+++ b/Lib/test/test_subprocess.py
@@ -1733,6 +1733,20 @@ def test_run_with_shell_timeout_and_capture_output(self):
msg="TimeoutExpired was delayed! Bad traceback:\n```\n"
f"{stacks}```")
+ def test_encoding_warning(self):
+ code = textwrap.dedent("""\
+ from subprocess import *
+ args = ["echo", "hello"]
+ run(args, text=True)
+ check_output(args, text=True)
+ """)
+ cp = subprocess.run([sys.executable, "-Xwarn_default_encoding", "-c", code],
+ capture_output=True)
+ lines = cp.stderr.splitlines()
+ self.assertEqual(len(lines), 2)
+ self.assertTrue(lines[0].startswith(b"<string>:3: EncodingWarning: "))
+ self.assertTrue(lines[1].startswith(b"<string>:4: EncodingWarning: "))
+
def _get_test_grp_name():
for name_group in ('staff', 'nogroup', 'grp', 'nobody', 'nfsnobody'):
diff --git a/Misc/NEWS.d/next/Library/2022-04-27-13-30-26.gh-issue-91954.cC7ga_.rst b/Misc/NEWS.d/next/Library/2022-04-27-13-30-26.gh-issue-91954.cC7ga_.rst
new file mode 100644
index 0000000000000..b63db25f32a4f
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-04-27-13-30-26.gh-issue-91954.cC7ga_.rst
@@ -0,0 +1,2 @@
+Add *encoding* and *errors* arguments to :func:`subprocess.getoutput` and
+:func:`subprocess.getstatusoutput`.
1
0
https://github.com/python/cpython/commit/c7b7f12b8609f932a23a9bc96a5de7cd9e…
commit: c7b7f12b8609f932a23a9bc96a5de7cd9ecd5723
branch: main
author: David Hewitt <1939362+davidhewitt(a)users.noreply.github.com>
committer: miss-islington <31488909+miss-islington(a)users.noreply.github.com>
date: 2022-04-29T22:23:54-07:00
summary:
gh-91880 - fix typo (GH-92069)
https://github.com/python/cpython/issues/91880#issuecomment-1113914241 - With thanks to @MojoVampire for spotting this.
Automerge-Triggered-By: GH:gvanrossum
files:
M Lib/asyncio/runners.py
diff --git a/Lib/asyncio/runners.py b/Lib/asyncio/runners.py
index d274576b10134..065691bed9928 100644
--- a/Lib/asyncio/runners.py
+++ b/Lib/asyncio/runners.py
@@ -106,7 +106,7 @@ def run(self, coro, *, context=None):
# `signal.signal` may throw if `threading.main_thread` does
# not support signals (e.g. embedded interpreter with signals
# not registered - see gh-91880)
- signal_handler = None
+ sigint_handler = None
else:
sigint_handler = None
1
0
bpo-43224: Implement substitution of unpacked TypeVarTuple in C (GH-31828)
by serhiy-storchaka April 30, 2022
by serhiy-storchaka April 30, 2022
April 30, 2022
https://github.com/python/cpython/commit/e8c2f72b94ae5dfba50c0f2e2c06b7ee97…
commit: e8c2f72b94ae5dfba50c0f2e2c06b7ee975c8acb
branch: main
author: Serhiy Storchaka <storchaka(a)gmail.com>
committer: serhiy-storchaka <storchaka(a)gmail.com>
date: 2022-04-30T08:22:46+03:00
summary:
bpo-43224: Implement substitution of unpacked TypeVarTuple in C (GH-31828)
Co-authored-by: Matthew Rahtz <mrahtz(a)gmail.com>
files:
M Include/internal/pycore_global_strings.h
M Include/internal/pycore_runtime_init.h
M Lib/test/test_typing.py
M Lib/typing.py
M Objects/genericaliasobject.c
diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h
index cc94662256e87..28fffa95071a0 100644
--- a/Include/internal/pycore_global_strings.h
+++ b/Include/internal/pycore_global_strings.h
@@ -202,6 +202,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(__truediv__)
STRUCT_FOR_ID(__trunc__)
STRUCT_FOR_ID(__typing_subst__)
+ STRUCT_FOR_ID(__typing_unpacked__)
STRUCT_FOR_ID(__warningregistry__)
STRUCT_FOR_ID(__weakref__)
STRUCT_FOR_ID(__xor__)
diff --git a/Include/internal/pycore_runtime_init.h b/Include/internal/pycore_runtime_init.h
index 9a3a9d04324ba..941badfc8cb6a 100644
--- a/Include/internal/pycore_runtime_init.h
+++ b/Include/internal/pycore_runtime_init.h
@@ -825,6 +825,7 @@ extern "C" {
INIT_ID(__truediv__), \
INIT_ID(__trunc__), \
INIT_ID(__typing_subst__), \
+ INIT_ID(__typing_unpacked__), \
INIT_ID(__warningregistry__), \
INIT_ID(__weakref__), \
INIT_ID(__xor__), \
diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index 412d117c238da..88be2850acb1c 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -754,89 +754,89 @@ class C(Generic[*Ts]): pass
tests = [
# Alias # Args # Expected result
('C[*Ts]', '[()]', 'C[()]'),
- ('tuple[*Ts]', '[()]', 'TypeError'), # Should be tuple[()]
+ ('tuple[*Ts]', '[()]', 'tuple[()]'),
('Tuple[*Ts]', '[()]', 'Tuple[()]'),
('C[*Ts]', '[int]', 'C[int]'),
- ('tuple[*Ts]', '[int]', 'tuple[(int,),]'), # Should be tuple[int]
+ ('tuple[*Ts]', '[int]', 'tuple[int]'),
('Tuple[*Ts]', '[int]', 'Tuple[int]'),
('C[*Ts]', '[int, str]', 'C[int, str]'),
- ('tuple[*Ts]', '[int, str]', 'TypeError'), # Should be tuple[int, str]
+ ('tuple[*Ts]', '[int, str]', 'tuple[int, str]'),
('Tuple[*Ts]', '[int, str]', 'Tuple[int, str]'),
('C[*Ts]', '[*tuple_type[int]]', 'C[*tuple_type[int]]'), # Should be C[int]
- ('tuple[*Ts]', '[*tuple_type[int]]', 'tuple[(*tuple_type[int],),]'), # Should be tuple[int]
+ ('tuple[*Ts]', '[*tuple_type[int]]', 'tuple[*tuple_type[int]]'), # Should be tuple[int]
('Tuple[*Ts]', '[*tuple_type[int]]', 'Tuple[*tuple_type[int]]'), # Should be Tuple[int]
('C[*Ts]', '[*tuple_type[*Ts]]', 'C[*tuple_type[*Ts]]'), # Should be C[*Ts]
- ('tuple[*Ts]', '[*tuple_type[*Ts]]', 'tuple[(*tuple_type[*Ts],),]'), # Should be tuple[*Ts]
+ ('tuple[*Ts]', '[*tuple_type[*Ts]]', 'tuple[*tuple_type[*Ts]]'), # Should be tuple[*Ts]
('Tuple[*Ts]', '[*tuple_type[*Ts]]', 'Tuple[*tuple_type[*Ts]]'), # Should be Tuple[*Ts]
('C[*Ts]', '[*tuple_type[int, str]]', 'C[*tuple_type[int, str]]'), # Should be C[int, str]
- ('tuple[*Ts]', '[*tuple_type[int, str]]', 'tuple[(*tuple_type[int, str],),]'), # Should be tuple[int, str]
+ ('tuple[*Ts]', '[*tuple_type[int, str]]', 'tuple[*tuple_type[int, str]]'), # Should be tuple[int, str]
('Tuple[*Ts]', '[*tuple_type[int, str]]', 'Tuple[*tuple_type[int, str]]'), # Should be Tuple[int, str]
('C[*Ts]', '[tuple_type[int, ...]]', 'C[tuple_type[int, ...]]'),
- ('tuple[*Ts]', '[tuple_type[int, ...]]', 'tuple[(tuple_type[int, ...],),]'), # Should be tuple[tuple_type[int, ...]]
+ ('tuple[*Ts]', '[tuple_type[int, ...]]', 'tuple[tuple_type[int, ...]]'),
('Tuple[*Ts]', '[tuple_type[int, ...]]', 'Tuple[tuple_type[int, ...]]'),
('C[*Ts]', '[tuple_type[int, ...], tuple_type[str, ...]]', 'C[tuple_type[int, ...], tuple_type[str, ...]]'),
- ('tuple[*Ts]', '[tuple_type[int, ...], tuple_type[str, ...]]', 'TypeError'), # Should be tuple[tuple_type[int, ...], tuple_type[str, ...]]
+ ('tuple[*Ts]', '[tuple_type[int, ...], tuple_type[str, ...]]', 'tuple[tuple_type[int, ...], tuple_type[str, ...]]'),
('Tuple[*Ts]', '[tuple_type[int, ...], tuple_type[str, ...]]', 'Tuple[tuple_type[int, ...], tuple_type[str, ...]]'),
('C[*Ts]', '[*tuple_type[int, ...]]', 'C[*tuple_type[int, ...]]'),
- ('tuple[*Ts]', '[*tuple_type[int, ...]]', 'tuple[(*tuple_type[int, ...],),]'), # Should be tuple[*tuple_type[int, ...]]
+ ('tuple[*Ts]', '[*tuple_type[int, ...]]', 'tuple[*tuple_type[int, ...]]'),
('Tuple[*Ts]', '[*tuple_type[int, ...]]', 'Tuple[*tuple_type[int, ...]]'),
# Technically, multiple unpackings are forbidden by PEP 646, but we
# choose to be less restrictive at runtime, to allow folks room
# to experiment. So all three of these should be valid.
('C[*Ts]', '[*tuple_type[int, ...], *tuple_type[str, ...]]', 'C[*tuple_type[int, ...], *tuple_type[str, ...]]'),
- # Should be tuple[*tuple_type[int, ...], *tuple_type[str, ...]], to match the other two.
- ('tuple[*Ts]', '[*tuple_type[int, ...], *tuple_type[str, ...]]', 'TypeError'),
+ ('tuple[*Ts]', '[*tuple_type[int, ...], *tuple_type[str, ...]]', 'tuple[*tuple_type[int, ...], *tuple_type[str, ...]]'),
('Tuple[*Ts]', '[*tuple_type[int, ...], *tuple_type[str, ...]]', 'Tuple[*tuple_type[int, ...], *tuple_type[str, ...]]'),
('C[*Ts]', '[*Ts]', 'C[*Ts]'),
- ('tuple[*Ts]', '[*Ts]', 'tuple[(*Ts,),]'), # Should be tuple[*Ts]
+ ('tuple[*Ts]', '[*Ts]', 'tuple[*Ts]'),
('Tuple[*Ts]', '[*Ts]', 'Tuple[*Ts]'),
('C[*Ts]', '[T, *Ts]', 'C[T, *Ts]'),
- ('tuple[*Ts]', '[T, *Ts]', 'TypeError'), # Should be tuple[T, *Ts]
+ ('tuple[*Ts]', '[T, *Ts]', 'tuple[T, *Ts]'),
('Tuple[*Ts]', '[T, *Ts]', 'Tuple[T, *Ts]'),
('C[*Ts]', '[*Ts, T]', 'C[*Ts, T]'),
- ('tuple[*Ts]', '[*Ts, T]', 'TypeError'), # Should be tuple[*Ts, T]
+ ('tuple[*Ts]', '[*Ts, T]', 'tuple[*Ts, T]'),
('Tuple[*Ts]', '[*Ts, T]', 'Tuple[*Ts, T]'),
('C[T, *Ts]', '[int]', 'C[int]'),
- ('tuple[T, *Ts]', '[int]', 'TypeError'), # Should be tuple[int]
+ ('tuple[T, *Ts]', '[int]', 'tuple[int]'),
('Tuple[T, *Ts]', '[int]', 'Tuple[int]'),
('C[T, *Ts]', '[int, str]', 'C[int, str]'),
- ('tuple[T, *Ts]', '[int, str]', 'tuple[int, (str,)]'), # Should be tuple[int, str]
+ ('tuple[T, *Ts]', '[int, str]', 'tuple[int, str]'),
('Tuple[T, *Ts]', '[int, str]', 'Tuple[int, str]'),
('C[T, *Ts]', '[int, str, bool]', 'C[int, str, bool]'),
- ('tuple[T, *Ts]', '[int, str, bool]', 'TypeError'), # Should be tuple[int, str, bool]
+ ('tuple[T, *Ts]', '[int, str, bool]', 'tuple[int, str, bool]'),
('Tuple[T, *Ts]', '[int, str, bool]', 'Tuple[int, str, bool]'),
('C[T, *Ts]', '[*tuple[int, ...]]', 'C[*tuple[int, ...]]'), # Should be C[int, *tuple[int, ...]]
('C[T, *Ts]', '[*Tuple[int, ...]]', 'TypeError'), # Ditto
- ('tuple[T, *Ts]', '[*tuple_type[int, ...]]', 'TypeError'), # Should be tuple[int, *tuple[int, ...]]
- ('Tuple[T, *Ts]', '[*tuple[int, ...]]', 'Tuple[*tuple[int, ...]]'), # Ditto
- ('Tuple[T, *Ts]', '[*Tuple[int, ...]]', 'TypeError'), # Ditto
+ ('tuple[T, *Ts]', '[*tuple[int, ...]]', 'tuple[*tuple[int, ...]]'), # Should be tuple[int, *tuple[int, ...]]
+ ('tuple[T, *Ts]', '[*Tuple[int, ...]]', 'TypeError'), # Should be tuple[int, *Tuple[int, ...]]
+ ('Tuple[T, *Ts]', '[*tuple[int, ...]]', 'Tuple[*tuple[int, ...]]'), # Should be Tuple[int, *tuple[int, ...]]
+ ('Tuple[T, *Ts]', '[*Tuple[int, ...]]', 'TypeError'), # Should be Tuple[int, *Tuple[int, ...]]
('C[*Ts, T]', '[int]', 'C[int]'),
- ('tuple[*Ts, T]', '[int]', 'TypeError'), # Should be tuple[int]
+ ('tuple[*Ts, T]', '[int]', 'tuple[int]'),
('Tuple[*Ts, T]', '[int]', 'Tuple[int]'),
('C[*Ts, T]', '[int, str]', 'C[int, str]'),
- ('tuple[*Ts, T]', '[int, str]', 'tuple[(int,), str]'), # Should be tuple[int, str]
+ ('tuple[*Ts, T]', '[int, str]', 'tuple[int, str]'),
('Tuple[*Ts, T]', '[int, str]', 'Tuple[int, str]'),
('C[*Ts, T]', '[int, str, bool]', 'C[int, str, bool]'),
- ('tuple[*Ts, T]', '[int, str, bool]', 'TypeError'), # Should be tuple[int, str, bool]
+ ('tuple[*Ts, T]', '[int, str, bool]', 'tuple[int, str, bool]'),
('Tuple[*Ts, T]', '[int, str, bool]', 'Tuple[int, str, bool]'),
('generic[T, *tuple_type[int, ...]]', '[str]', 'generic[str, *tuple_type[int, ...]]'),
@@ -945,7 +945,7 @@ def test_var_substitution(self):
T2 = TypeVar('T2')
class G(Generic[Unpack[Ts]]): pass
- for A in G, Tuple:
+ for A in G, Tuple, tuple:
B = A[Unpack[Ts]]
self.assertEqual(B[()], A[()])
self.assertEqual(B[float], A[float])
@@ -984,6 +984,21 @@ def test_bad_var_substitution(self):
T2 = TypeVar('T2')
class G(Generic[Unpack[Ts]]): pass
+ for A in G, Tuple, tuple:
+ B = A[Ts]
+ with self.assertRaises(TypeError):
+ B[int, str]
+
+ C = A[T, T2]
+ with self.assertRaises(TypeError):
+ C[Unpack[Ts]]
+
+ def test_repr_is_correct(self):
+ Ts = TypeVarTuple('Ts')
+ T = TypeVar('T')
+ T2 = TypeVar('T2')
+ class G(Generic[Unpack[Ts]]): pass
+
for A in G, Tuple:
B = A[T, Unpack[Ts], str, T2]
with self.assertRaises(TypeError):
diff --git a/Lib/typing.py b/Lib/typing.py
index b250f2992dfff..35deb32220eb8 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -1019,7 +1019,7 @@ def __repr__(self):
return self.__name__
def __typing_subst__(self, arg):
- raise AssertionError
+ raise TypeError("Substitution of bare TypeVarTuple is not supported")
class ParamSpecArgs(_Final, _Immutable, _root=True):
@@ -1686,11 +1686,15 @@ def __repr__(self):
return '*' + repr(self.__args__[0])
def __getitem__(self, args):
- if (len(self.__parameters__) == 1 and
- isinstance(self.__parameters__[0], TypeVarTuple)):
+ if self.__typing_unpacked__():
return args
return super().__getitem__(args)
+ def __typing_unpacked__(self):
+ # If x is Unpack[tuple[...]], __parameters__ will be empty.
+ return bool(self.__parameters__ and
+ isinstance(self.__parameters__[0], TypeVarTuple))
+
class Generic:
"""Abstract base class for generic types.
diff --git a/Objects/genericaliasobject.c b/Objects/genericaliasobject.c
index 7059c4018303e..7b689912dffc1 100644
--- a/Objects/genericaliasobject.c
+++ b/Objects/genericaliasobject.c
@@ -190,6 +190,23 @@ tuple_add(PyObject *self, Py_ssize_t len, PyObject *item)
return 0;
}
+static Py_ssize_t
+tuple_extend(PyObject **dst, Py_ssize_t dstindex,
+ PyObject **src, Py_ssize_t count)
+{
+ assert(count >= 0);
+ if (_PyTuple_Resize(dst, PyTuple_GET_SIZE(*dst) + count - 1) != 0) {
+ return -1;
+ }
+ assert(dstindex + count <= PyTuple_GET_SIZE(*dst));
+ for (Py_ssize_t i = 0; i < count; ++i) {
+ PyObject *item = src[i];
+ Py_INCREF(item);
+ PyTuple_SET_ITEM(*dst, dstindex + i, item);
+ }
+ return dstindex + count;
+}
+
PyObject *
_Py_make_parameters(PyObject *args)
{
@@ -251,7 +268,8 @@ _Py_make_parameters(PyObject *args)
If obj doesn't have a __parameters__ attribute or that's not
a non-empty tuple, return a new reference to obj. */
static PyObject *
-subs_tvars(PyObject *obj, PyObject *params, PyObject **argitems)
+subs_tvars(PyObject *obj, PyObject *params,
+ PyObject **argitems, Py_ssize_t nargs, Py_ssize_t varparam)
{
PyObject *subparams;
if (_PyObject_LookupAttr(obj, &_Py_ID(__parameters__), &subparams) < 0) {
@@ -265,14 +283,27 @@ subs_tvars(PyObject *obj, PyObject *params, PyObject **argitems)
Py_DECREF(subparams);
return NULL;
}
- for (Py_ssize_t i = 0; i < nsubargs; ++i) {
+ for (Py_ssize_t i = 0, j = 0; i < nsubargs; ++i) {
PyObject *arg = PyTuple_GET_ITEM(subparams, i);
Py_ssize_t iparam = tuple_index(params, nparams, arg);
- if (iparam >= 0) {
- arg = argitems[iparam];
+ if (iparam == varparam) {
+ j = tuple_extend(&subargs, j,
+ argitems + iparam, nargs - nparams + 1);
+ if (j < 0) {
+ return NULL;
+ }
+ }
+ else {
+ if (iparam >= 0) {
+ if (iparam > varparam) {
+ iparam += nargs - nsubargs;
+ }
+ arg = argitems[iparam];
+ }
+ Py_INCREF(arg);
+ PyTuple_SET_ITEM(subargs, j, arg);
+ j++;
}
- Py_INCREF(arg);
- PyTuple_SET_ITEM(subargs, i, arg);
}
obj = PyObject_GetItem(obj, subargs);
@@ -286,6 +317,23 @@ subs_tvars(PyObject *obj, PyObject *params, PyObject **argitems)
return obj;
}
+static int
+_is_unpacked_typevartuple(PyObject *arg)
+{
+ PyObject *meth;
+ int res = _PyObject_LookupAttr(arg, &_Py_ID(__typing_unpacked__), &meth);
+ if (res > 0) {
+ PyObject *tmp = PyObject_CallNoArgs(meth);
+ Py_DECREF(meth);
+ if (tmp == NULL) {
+ return -1;
+ }
+ res = PyObject_IsTrue(tmp);
+ Py_DECREF(tmp);
+ }
+ return res;
+}
+
PyObject *
_Py_subs_parameters(PyObject *self, PyObject *args, PyObject *parameters, PyObject *item)
{
@@ -298,11 +346,27 @@ _Py_subs_parameters(PyObject *self, PyObject *args, PyObject *parameters, PyObje
int is_tuple = PyTuple_Check(item);
Py_ssize_t nitems = is_tuple ? PyTuple_GET_SIZE(item) : 1;
PyObject **argitems = is_tuple ? &PyTuple_GET_ITEM(item, 0) : &item;
- if (nitems != nparams) {
- return PyErr_Format(PyExc_TypeError,
- "Too %s arguments for %R",
- nitems > nparams ? "many" : "few",
- self);
+ Py_ssize_t varparam = 0;
+ for (; varparam < nparams; varparam++) {
+ PyObject *param = PyTuple_GET_ITEM(parameters, varparam);
+ if (Py_TYPE(param)->tp_iter) { // TypeVarTuple
+ break;
+ }
+ }
+ if (varparam < nparams) {
+ if (nitems < nparams - 1) {
+ return PyErr_Format(PyExc_TypeError,
+ "Too few arguments for %R",
+ self);
+ }
+ }
+ else {
+ if (nitems != nparams) {
+ return PyErr_Format(PyExc_TypeError,
+ "Too %s arguments for %R",
+ nitems > nparams ? "many" : "few",
+ self);
+ }
}
/* Replace all type variables (specified by parameters)
with corresponding values specified by argitems.
@@ -315,8 +379,13 @@ _Py_subs_parameters(PyObject *self, PyObject *args, PyObject *parameters, PyObje
if (newargs == NULL) {
return NULL;
}
- for (Py_ssize_t iarg = 0; iarg < nargs; iarg++) {
+ for (Py_ssize_t iarg = 0, jarg = 0; iarg < nargs; iarg++) {
PyObject *arg = PyTuple_GET_ITEM(args, iarg);
+ int unpack = _is_unpacked_typevartuple(arg);
+ if (unpack < 0) {
+ Py_DECREF(newargs);
+ return NULL;
+ }
PyObject *subst;
if (_PyObject_LookupAttr(arg, &_Py_ID(__typing_subst__), &subst) < 0) {
Py_DECREF(newargs);
@@ -325,17 +394,38 @@ _Py_subs_parameters(PyObject *self, PyObject *args, PyObject *parameters, PyObje
if (subst) {
Py_ssize_t iparam = tuple_index(parameters, nparams, arg);
assert(iparam >= 0);
+ if (iparam == varparam) {
+ Py_DECREF(subst);
+ Py_DECREF(newargs);
+ PyErr_SetString(PyExc_TypeError,
+ "Substitution of bare TypeVarTuple is not supported");
+ return NULL;
+ }
+ if (iparam > varparam) {
+ iparam += nitems - nparams;
+ }
arg = PyObject_CallOneArg(subst, argitems[iparam]);
Py_DECREF(subst);
}
else {
- arg = subs_tvars(arg, parameters, argitems);
+ arg = subs_tvars(arg, parameters, argitems, nitems, varparam);
}
if (arg == NULL) {
Py_DECREF(newargs);
return NULL;
}
- PyTuple_SET_ITEM(newargs, iarg, arg);
+ if (unpack) {
+ jarg = tuple_extend(&newargs, jarg,
+ &PyTuple_GET_ITEM(arg, 0), PyTuple_GET_SIZE(arg));
+ Py_DECREF(arg);
+ if (jarg < 0) {
+ return NULL;
+ }
+ }
+ else {
+ PyTuple_SET_ITEM(newargs, jarg, arg);
+ jarg++;
+ }
}
return newargs;
1
0
gh-92064: Fix global variable name collision in test_typing (#92067)
by JelleZijlstra April 30, 2022
by JelleZijlstra April 30, 2022
April 30, 2022
https://github.com/python/cpython/commit/a29aa76a3ff8e5a4ee85961bb37a163f6b…
commit: a29aa76a3ff8e5a4ee85961bb37a163f6b75a034
branch: main
author: Dennis Sweeney <36520290+sweeneyde(a)users.noreply.github.com>
committer: JelleZijlstra <jelle.zijlstra(a)gmail.com>
date: 2022-04-29T21:18:38-06:00
summary:
gh-92064: Fix global variable name collision in test_typing (#92067)
Fixes #92064
files:
M Lib/test/test_typing.py
diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index 929f0df960ae0..412d117c238da 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -1332,16 +1332,16 @@ class TypeVarTuplePicklingTests(BaseTestCase):
@all_pickle_protocols
def test_pickling_then_unpickling_results_in_same_identity(self, proto):
- global Ts1 # See explanation at start of class.
- Ts1 = TypeVarTuple('Ts1')
- Ts2 = pickle.loads(pickle.dumps(Ts1, proto))
- self.assertIs(Ts1, Ts2)
+ global global_Ts1 # See explanation at start of class.
+ global_Ts1 = TypeVarTuple('global_Ts1')
+ global_Ts2 = pickle.loads(pickle.dumps(global_Ts1, proto))
+ self.assertIs(global_Ts1, global_Ts2)
@all_pickle_protocols
def test_pickling_then_unpickling_unpacked_results_in_same_identity(self, proto):
- global Ts # See explanation at start of class.
- Ts = TypeVarTuple('Ts')
- unpacked1 = Unpack[Ts]
+ global global_Ts # See explanation at start of class.
+ global_Ts = TypeVarTuple('global_Ts')
+ unpacked1 = Unpack[global_Ts]
unpacked2 = pickle.loads(pickle.dumps(unpacked1, proto))
self.assertIs(unpacked1, unpacked2)
@@ -1349,19 +1349,19 @@ def test_pickling_then_unpickling_unpacked_results_in_same_identity(self, proto)
def test_pickling_then_unpickling_tuple_with_typevartuple_equality(
self, proto
):
- global T, Ts # See explanation at start of class.
- T = TypeVar('T')
- Ts = TypeVarTuple('Ts')
+ global global_T, global_Ts # See explanation at start of class.
+ global_T = TypeVar('global_T')
+ global_Ts = TypeVarTuple('global_Ts')
- a1 = Tuple[Unpack[Ts]]
+ a1 = Tuple[Unpack[global_Ts]]
a2 = pickle.loads(pickle.dumps(a1, proto))
self.assertEqual(a1, a2)
- a1 = Tuple[T, Unpack[Ts]]
+ a1 = Tuple[T, Unpack[global_Ts]]
a2 = pickle.loads(pickle.dumps(a1, proto))
self.assertEqual(a1, a2)
- a1 = Tuple[int, Unpack[Ts]]
+ a1 = Tuple[int, Unpack[global_Ts]]
a2 = pickle.loads(pickle.dumps(a1, proto))
self.assertEqual(a1, a2)
1
0