Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-36346: Emit DeprecationWarning for PyArg_Parse() with 'u' or 'Z'. #20927

Merged
merged 3 commits into from
Feb 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 59 additions & 24 deletions Lib/test/test_getargs2.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import sys
from test import support
from test.support import import_helper
from test.support import warnings_helper
# Skip this test if the _testcapi module isn't available.
_testcapi = import_helper.import_module('_testcapi')
from _testcapi import getargs_keywords, getargs_keyword_only
Expand Down Expand Up @@ -979,42 +980,66 @@ def test_et_hash(self):
@support.requires_legacy_unicode_capi
def test_u(self):
from _testcapi import getargs_u
self.assertEqual(getargs_u('abc\xe9'), 'abc\xe9')
self.assertRaises(ValueError, getargs_u, 'nul:\0')
self.assertRaises(TypeError, getargs_u, b'bytes')
self.assertRaises(TypeError, getargs_u, bytearray(b'bytearray'))
self.assertRaises(TypeError, getargs_u, memoryview(b'memoryview'))
self.assertRaises(TypeError, getargs_u, None)
with self.assertWarns(DeprecationWarning):
self.assertEqual(getargs_u('abc\xe9'), 'abc\xe9')
with self.assertWarns(DeprecationWarning):
self.assertRaises(ValueError, getargs_u, 'nul:\0')
with self.assertWarns(DeprecationWarning):
self.assertRaises(TypeError, getargs_u, b'bytes')
with self.assertWarns(DeprecationWarning):
self.assertRaises(TypeError, getargs_u, bytearray(b'bytearray'))
with self.assertWarns(DeprecationWarning):
self.assertRaises(TypeError, getargs_u, memoryview(b'memoryview'))
with self.assertWarns(DeprecationWarning):
self.assertRaises(TypeError, getargs_u, None)

@support.requires_legacy_unicode_capi
def test_u_hash(self):
from _testcapi import getargs_u_hash
self.assertEqual(getargs_u_hash('abc\xe9'), 'abc\xe9')
self.assertEqual(getargs_u_hash('nul:\0'), 'nul:\0')
self.assertRaises(TypeError, getargs_u_hash, b'bytes')
self.assertRaises(TypeError, getargs_u_hash, bytearray(b'bytearray'))
self.assertRaises(TypeError, getargs_u_hash, memoryview(b'memoryview'))
self.assertRaises(TypeError, getargs_u_hash, None)
with self.assertWarns(DeprecationWarning):
self.assertEqual(getargs_u_hash('abc\xe9'), 'abc\xe9')
with self.assertWarns(DeprecationWarning):
self.assertEqual(getargs_u_hash('nul:\0'), 'nul:\0')
with self.assertWarns(DeprecationWarning):
self.assertRaises(TypeError, getargs_u_hash, b'bytes')
with self.assertWarns(DeprecationWarning):
self.assertRaises(TypeError, getargs_u_hash, bytearray(b'bytearray'))
with self.assertWarns(DeprecationWarning):
self.assertRaises(TypeError, getargs_u_hash, memoryview(b'memoryview'))
with self.assertWarns(DeprecationWarning):
self.assertRaises(TypeError, getargs_u_hash, None)

@support.requires_legacy_unicode_capi
def test_Z(self):
from _testcapi import getargs_Z
self.assertEqual(getargs_Z('abc\xe9'), 'abc\xe9')
self.assertRaises(ValueError, getargs_Z, 'nul:\0')
self.assertRaises(TypeError, getargs_Z, b'bytes')
self.assertRaises(TypeError, getargs_Z, bytearray(b'bytearray'))
self.assertRaises(TypeError, getargs_Z, memoryview(b'memoryview'))
self.assertIsNone(getargs_Z(None))
with self.assertWarns(DeprecationWarning):
self.assertEqual(getargs_Z('abc\xe9'), 'abc\xe9')
with self.assertWarns(DeprecationWarning):
self.assertRaises(ValueError, getargs_Z, 'nul:\0')
with self.assertWarns(DeprecationWarning):
self.assertRaises(TypeError, getargs_Z, b'bytes')
with self.assertWarns(DeprecationWarning):
self.assertRaises(TypeError, getargs_Z, bytearray(b'bytearray'))
with self.assertWarns(DeprecationWarning):
self.assertRaises(TypeError, getargs_Z, memoryview(b'memoryview'))
with self.assertWarns(DeprecationWarning):
self.assertIsNone(getargs_Z(None))

@support.requires_legacy_unicode_capi
def test_Z_hash(self):
from _testcapi import getargs_Z_hash
self.assertEqual(getargs_Z_hash('abc\xe9'), 'abc\xe9')
self.assertEqual(getargs_Z_hash('nul:\0'), 'nul:\0')
self.assertRaises(TypeError, getargs_Z_hash, b'bytes')
self.assertRaises(TypeError, getargs_Z_hash, bytearray(b'bytearray'))
self.assertRaises(TypeError, getargs_Z_hash, memoryview(b'memoryview'))
self.assertIsNone(getargs_Z_hash(None))
with self.assertWarns(DeprecationWarning):
self.assertEqual(getargs_Z_hash('abc\xe9'), 'abc\xe9')
with self.assertWarns(DeprecationWarning):
self.assertEqual(getargs_Z_hash('nul:\0'), 'nul:\0')
with self.assertWarns(DeprecationWarning):
self.assertRaises(TypeError, getargs_Z_hash, b'bytes')
with self.assertWarns(DeprecationWarning):
self.assertRaises(TypeError, getargs_Z_hash, bytearray(b'bytearray'))
with self.assertWarns(DeprecationWarning):
self.assertRaises(TypeError, getargs_Z_hash, memoryview(b'memoryview'))
with self.assertWarns(DeprecationWarning):
self.assertIsNone(getargs_Z_hash(None))


class Object_TestCase(unittest.TestCase):
Expand Down Expand Up @@ -1053,6 +1078,8 @@ def test(self):

class SkipitemTest(unittest.TestCase):

# u, and Z raises DeprecationWarning
@warnings_helper.ignore_warnings(category=DeprecationWarning)
def test_skipitem(self):
"""
If this test failed, you probably added a new "format unit"
Expand Down Expand Up @@ -1221,6 +1248,14 @@ class Test_testcapi(unittest.TestCase):
for name in dir(_testcapi)
if name.startswith('test_') and name.endswith('_code'))

@warnings_helper.ignore_warnings(category=DeprecationWarning)
def test_u_code(self):
_testcapi.test_u_code()

@warnings_helper.ignore_warnings(category=DeprecationWarning)
def test_Z_code(self):
_testcapi.test_Z_code()


if __name__ == "__main__":
unittest.main()
6 changes: 4 additions & 2 deletions Lib/test/test_unicode.py
Original file line number Diff line number Diff line change
Expand Up @@ -2362,12 +2362,14 @@ def test_resize(self):
text = 'a' * length + 'b'

# fill wstr internal field
abc = getargs_u(text)
with self.assertWarns(DeprecationWarning):
abc = getargs_u(text)
self.assertEqual(abc, text)

# resize text: wstr field must be cleared and then recomputed
text += 'c'
abcdef = getargs_u(text)
with self.assertWarns(DeprecationWarning):
abcdef = getargs_u(text)
self.assertNotEqual(abc, abcdef)
self.assertEqual(abcdef, text)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
``PyArg_Parse*()`` functions now emits ``DeprecationWarning`` when ``u`` or
``Z`` format is used. See :pep:`623` for detail.
5 changes: 4 additions & 1 deletion Python/getargs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1014,7 +1014,10 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
case 'u': /* raw unicode buffer (Py_UNICODE *) */
case 'Z': /* raw unicode buffer or None */
{
// TODO: Raise DeprecationWarning
if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1,
"getargs: The '%c' format is deprecated. Use 'U' instead.", c)) {
return NULL;
}
_Py_COMP_DIAG_PUSH
_Py_COMP_DIAG_IGNORE_DEPR_DECLS
Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **);
Expand Down