From 26f01fa865b17b9c5c0915b14a4c9cf74a362118 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sat, 31 May 2025 16:04:34 +0200 Subject: [PATCH 1/4] deprecate `string` keyword parameter for hash function constructors --- Doc/deprecations/pending-removal-in-3.17.rst | 11 ++++++++++ Doc/library/hashlib.rst | 7 +++++++ Doc/whatsnew/3.15.rst | 11 ++++++++-- Lib/test/test_hashlib.py | 20 ++++++++++++++++--- ...-05-31-15-49-46.gh-issue-134978.mXXuvW.rst | 5 +++++ Modules/hashlib.h | 9 +++++++++ 6 files changed, 58 insertions(+), 5 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2025-05-31-15-49-46.gh-issue-134978.mXXuvW.rst diff --git a/Doc/deprecations/pending-removal-in-3.17.rst b/Doc/deprecations/pending-removal-in-3.17.rst index 370b98307e5228..7983f8cd575738 100644 --- a/Doc/deprecations/pending-removal-in-3.17.rst +++ b/Doc/deprecations/pending-removal-in-3.17.rst @@ -1,6 +1,17 @@ Pending removal in Python 3.17 ------------------------------ +* :mod:`hashlib`: + + - Supporting the undocumented ``string`` keyword parameter in :func:`~hashlib.new` + and hash function constructors such as :func:`~hashlib.md5` is deprecated. + Use the ``data`` keyword parameter instead, or simply pass the data to hash + as a positional argument. + + Before Python 3.13, the ``string`` keyword parameter was not correctly + supported depending on the backend implementation of hash functions, and + users should prefer passing the data to hash as a positional argument. + * :mod:`typing`: - Before Python 3.14, old-style unions were implemented using the private class diff --git a/Doc/library/hashlib.rst b/Doc/library/hashlib.rst index 4818a4944a512a..ee712bc2bd9875 100644 --- a/Doc/library/hashlib.rst +++ b/Doc/library/hashlib.rst @@ -94,6 +94,13 @@ accessible by name via :func:`new`. See :data:`algorithms_available`. OpenSSL does not provide we fall back to a verified implementation from the `HACL\* project`_. +.. deprecated-removed:: 3.15 3.17 + The undocumented ``string`` keyword parameter in :func:`new` and hash + function constructors such as :func:`md5` is deprecated. + Use the ``data`` keyword parameter instead, or simply pass the data to hash + as a positional argument. + + Usage ----- diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 6d1f653f086a15..ae9b2d5013dccb 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -129,8 +129,15 @@ module_name Deprecated ========== -* module_name: - TODO +hashlib +------- + +* Supporting the undocumented ``string`` keyword parameter in + :func:`~hashlib.new` and hash function constructors such as + :func:`~hashlib.md5` is deprecated and slated for removal in Python 3.17. + Use the ``data`` keyword parameter instead, or simply pass the data to hash + as a positional argument. + (Contributed by Bénédikt Tran in :gh:`134978`.) .. Add deprecations above alphabetically, not here at the end. diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py index 8244f7c7553a37..c7db43d1bc7d1b 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -98,6 +98,14 @@ def read_vectors(hash_name): yield parts +DEPRECATED_STRING_PARAMETER = re.escape( + "the 'string' keyword parameter is deprecated since " + "Python 3.15 and slated for removal in Python 3.17; " + "use the 'data' keyword parameter or pass the data " + "to hash as a positional argument instead" +) + + class HashLibTestCase(unittest.TestCase): supported_hash_names = ( 'md5', 'MD5', 'sha1', 'SHA1', 'sha224', 'SHA224', 'sha256', 'SHA256', @@ -255,17 +263,23 @@ def test_clinic_signature(self): with self.subTest(constructor.__name__): constructor(b'') constructor(data=b'') - constructor(string=b'') # should be deprecated in the future + with self.assertWarnsRegex(DeprecationWarning, + DEPRECATED_STRING_PARAMETER): + constructor(string=b'') digest_name = constructor(b'').name with self.subTest(digest_name): hashlib.new(digest_name, b'') hashlib.new(digest_name, data=b'') - hashlib.new(digest_name, string=b'') + with self.assertWarnsRegex(DeprecationWarning, + DEPRECATED_STRING_PARAMETER): + hashlib.new(digest_name, string=b'') if self._hashlib: self._hashlib.new(digest_name, b'') self._hashlib.new(digest_name, data=b'') - self._hashlib.new(digest_name, string=b'') + with self.assertWarnsRegex(DeprecationWarning, + DEPRECATED_STRING_PARAMETER): + self._hashlib.new(digest_name, string=b'') @unittest.skipIf(get_fips_mode(), "skip in FIPS mode") def test_clinic_signature_errors(self): diff --git a/Misc/NEWS.d/next/Library/2025-05-31-15-49-46.gh-issue-134978.mXXuvW.rst b/Misc/NEWS.d/next/Library/2025-05-31-15-49-46.gh-issue-134978.mXXuvW.rst new file mode 100644 index 00000000000000..9f7ff21f699410 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-05-31-15-49-46.gh-issue-134978.mXXuvW.rst @@ -0,0 +1,5 @@ +Supporting the undocumented ``string`` keyword parameter in :func:`hashlib.new` +and hash function constructors such as :func:`hashlib.md5` is deprecated and +slated for removal in Python 3.17. Use the ``data`` keyword parameter instead, +or simply pass the data to hash as a positional argument. +Patch by Bénédikt Tran. diff --git a/Modules/hashlib.h b/Modules/hashlib.h index a80b195a765792..fa796c04221cc7 100644 --- a/Modules/hashlib.h +++ b/Modules/hashlib.h @@ -86,6 +86,15 @@ _Py_hashlib_data_argument(PyObject **res, PyObject *data, PyObject *string) } else if (data == NULL && string != NULL) { // called as H(string=...) + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "the 'string' keyword parameter is deprecated since " + "Python 3.15 and slated for removal in Python 3.17; " + "use the 'data' keyword parameter or pass the data " + "to hash as a positional argument instead", 1) < 0) + { + *res = NULL; + return -1; + } *res = string; return 1; } From ae0e0c3a302777f47ca36591fb001aca472a0f55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sun, 1 Jun 2025 10:36:38 +0200 Subject: [PATCH 2/4] amend deprecation notes --- Doc/deprecations/pending-removal-in-3.17.rst | 11 ----------- Doc/deprecations/pending-removal-in-3.19.rst | 16 ++++++++++++++++ Doc/whatsnew/3.15.rst | 15 ++++++++++----- ...025-05-31-15-49-46.gh-issue-134978.mXXuvW.rst | 10 ++++++---- 4 files changed, 32 insertions(+), 20 deletions(-) diff --git a/Doc/deprecations/pending-removal-in-3.17.rst b/Doc/deprecations/pending-removal-in-3.17.rst index 7983f8cd575738..370b98307e5228 100644 --- a/Doc/deprecations/pending-removal-in-3.17.rst +++ b/Doc/deprecations/pending-removal-in-3.17.rst @@ -1,17 +1,6 @@ Pending removal in Python 3.17 ------------------------------ -* :mod:`hashlib`: - - - Supporting the undocumented ``string`` keyword parameter in :func:`~hashlib.new` - and hash function constructors such as :func:`~hashlib.md5` is deprecated. - Use the ``data`` keyword parameter instead, or simply pass the data to hash - as a positional argument. - - Before Python 3.13, the ``string`` keyword parameter was not correctly - supported depending on the backend implementation of hash functions, and - users should prefer passing the data to hash as a positional argument. - * :mod:`typing`: - Before Python 3.14, old-style unions were implemented using the private class diff --git a/Doc/deprecations/pending-removal-in-3.19.rst b/Doc/deprecations/pending-removal-in-3.19.rst index 3936f63ca5b5af..25f9cba390de68 100644 --- a/Doc/deprecations/pending-removal-in-3.19.rst +++ b/Doc/deprecations/pending-removal-in-3.19.rst @@ -6,3 +6,19 @@ Pending removal in Python 3.19 * Implicitly switching to the MSVC-compatible struct layout by setting :attr:`~ctypes.Structure._pack_` but not :attr:`~ctypes.Structure._layout_` on non-Windows platforms. + +* :mod:`hashlib`: + + - In hash function constructors such as :func:`~hashlib.new` or the + direct hash-named constructors such as :func:`~hashlib.md5` and + :func:`~hashlib.sha256`, their optional initial data parameter could + also be passed a keyword argument named ``data=`` or ``string=`` in + various :mod:`!hashlib` implementations. + + Support for the ``string`` keyword argument name is now deprecated + and slated for removal in Python 3.19. + + Before Python 3.13, the ``string`` keyword parameter was not correctly + supported depending on the backend implementation of hash functions. + Prefer passing the initial data as a positional argument for maximum + backwards compatibility. diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index ae9b2d5013dccb..709d554dea983e 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -132,11 +132,16 @@ Deprecated hashlib ------- -* Supporting the undocumented ``string`` keyword parameter in - :func:`~hashlib.new` and hash function constructors such as - :func:`~hashlib.md5` is deprecated and slated for removal in Python 3.17. - Use the ``data`` keyword parameter instead, or simply pass the data to hash - as a positional argument. +* In hash function constructors such as :func:`~hashlib.new` or the + direct hash-named constructors such as :func:`~hashlib.md5` and + :func:`~hashlib.sha256`, their optional initial data parameter could + also be passed a keyword argument named ``data=`` or ``string=`` in + various :mod:`hashlib` implementations. + + Support for the ``string`` keyword argument name is now deprecated and + is slated for removal in Python 3.19. Prefer passing the initial data as + a positional argument for maximum backwards compatibility. + (Contributed by Bénédikt Tran in :gh:`134978`.) diff --git a/Misc/NEWS.d/next/Library/2025-05-31-15-49-46.gh-issue-134978.mXXuvW.rst b/Misc/NEWS.d/next/Library/2025-05-31-15-49-46.gh-issue-134978.mXXuvW.rst index 9f7ff21f699410..e75ce1622d6396 100644 --- a/Misc/NEWS.d/next/Library/2025-05-31-15-49-46.gh-issue-134978.mXXuvW.rst +++ b/Misc/NEWS.d/next/Library/2025-05-31-15-49-46.gh-issue-134978.mXXuvW.rst @@ -1,5 +1,7 @@ -Supporting the undocumented ``string`` keyword parameter in :func:`hashlib.new` -and hash function constructors such as :func:`hashlib.md5` is deprecated and -slated for removal in Python 3.17. Use the ``data`` keyword parameter instead, -or simply pass the data to hash as a positional argument. +:mod:`hashlib`: Supporting the ``string`` keyword parameter in hash function +constructors such as :func:`~hashlib.new` or the direct hash-named constructors +such as :func:`~hashlib.md5` and :func:`~hashlib.sha256` is now deprecated and +slated for removal in Python 3.19. +Prefer passing the initial data as a positional argument for maximum backwards +compatibility. Patch by Bénédikt Tran. From 7f87b057faf38b6c1f3162c07983bc570a0f58b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sun, 1 Jun 2025 10:37:50 +0200 Subject: [PATCH 3/4] update warning --- Doc/library/hashlib.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/library/hashlib.rst b/Doc/library/hashlib.rst index ee712bc2bd9875..8bba6700930bf4 100644 --- a/Doc/library/hashlib.rst +++ b/Doc/library/hashlib.rst @@ -94,11 +94,11 @@ accessible by name via :func:`new`. See :data:`algorithms_available`. OpenSSL does not provide we fall back to a verified implementation from the `HACL\* project`_. -.. deprecated-removed:: 3.15 3.17 - The undocumented ``string`` keyword parameter in :func:`new` and hash - function constructors such as :func:`md5` is deprecated. - Use the ``data`` keyword parameter instead, or simply pass the data to hash - as a positional argument. +.. deprecated-removed:: 3.15 3.19 + The undocumented ``string`` keyword parameter in :func:`!_hashlib.new` + and hash-named constructors such as :func:`!_md5.md5` is deprecated. + Prefer passing the initial data as a positional argument for maximum + backwards compatibility. Usage From 80ce66db2954283f4a9afbd1bedb16eef84804e5 Mon Sep 17 00:00:00 2001 From: "Gregory P. Smith" Date: Sun, 1 Jun 2025 20:59:04 -0700 Subject: [PATCH 4/4] 3.19 in the warning --- Lib/test/test_hashlib.py | 2 +- Modules/hashlib.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py index c7db43d1bc7d1b..b83ae181718b7a 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -100,7 +100,7 @@ def read_vectors(hash_name): DEPRECATED_STRING_PARAMETER = re.escape( "the 'string' keyword parameter is deprecated since " - "Python 3.15 and slated for removal in Python 3.17; " + "Python 3.15 and slated for removal in Python 3.19; " "use the 'data' keyword parameter or pass the data " "to hash as a positional argument instead" ) diff --git a/Modules/hashlib.h b/Modules/hashlib.h index fa796c04221cc7..e82ec92be25c57 100644 --- a/Modules/hashlib.h +++ b/Modules/hashlib.h @@ -88,7 +88,7 @@ _Py_hashlib_data_argument(PyObject **res, PyObject *data, PyObject *string) // called as H(string=...) if (PyErr_WarnEx(PyExc_DeprecationWarning, "the 'string' keyword parameter is deprecated since " - "Python 3.15 and slated for removal in Python 3.17; " + "Python 3.15 and slated for removal in Python 3.19; " "use the 'data' keyword parameter or pass the data " "to hash as a positional argument instead", 1) < 0) {