https://github.com/python/cpython/commit/7ce2f101c4b1c123860c90bf67ccc20a7805ea48
commit: 7ce2f101c4b1c123860c90bf67ccc20a7805ea48
branch: main
author: Bénédikt Tran <[email protected]>
committer: picnixz <[email protected]>
date: 2025-07-25T14:49:09Z
summary:
gh-136929: ensure that `hashlib.<name>` does not raise `AttributeError`
(#136933)
Previously, if OpenSSL was not present and built-in cryptographic extension
modules
were disabled, requesting `hashlib.<name>` raised `AttributeError` and an ERROR
log
message with the exception traceback is emitted when importing `hashlib`.
Now, the named constructor function will always be available but raises a
`ValueError`
at runtime indicating that the algorithm is not supported. The log message has
also
been reworded to be less verbose.
files:
A Misc/NEWS.d/next/Library/2025-07-21-16-13-20.gh-issue-136929.obKZ2S.rst
M Doc/whatsnew/3.15.rst
M Lib/hashlib.py
diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst
index e8e2c1ed6047bf..1128da875a8847 100644
--- a/Doc/whatsnew/3.15.rst
+++ b/Doc/whatsnew/3.15.rst
@@ -230,6 +230,17 @@ difflib
(Contributed by Jiahao Li in :gh:`134580`.)
+hashlib
+-------
+
+* Ensure that hash functions guaranteed to be always *available* exist as
+ attributes of :mod:`hashlib` even if they will not work at runtime due to
+ missing backend implementations. For instance, ``hashlib.md5`` will no
+ longer raise :exc:`AttributeError` if OpenSSL is not available and Python
+ has been built without MD5 support.
+ (Contributed by Bénédikt Tran in :gh:`136929`.)
+
+
http.client
-----------
diff --git a/Lib/hashlib.py b/Lib/hashlib.py
index a7db778b716537..8e7083ba692348 100644
--- a/Lib/hashlib.py
+++ b/Lib/hashlib.py
@@ -261,16 +261,39 @@ def file_digest(fileobj, digest, /, *, _bufsize=2**18):
return digestobj
+__logging = None
for __func_name in __always_supported:
# try them all, some may not work due to the OpenSSL
# version not supporting that algorithm.
try:
globals()[__func_name] = __get_hash(__func_name)
- except ValueError:
- import logging
- logging.exception('code for hash %s was not found.', __func_name)
-
+ except ValueError as __exc:
+ import logging as __logging
+ __logging.error('hash algorithm %s will not be supported at runtime '
+ '[reason: %s]', __func_name, __exc)
+ # The following code can be simplified in Python 3.19
+ # once "string" is removed from the signature.
+ __code = f'''\
+def {__func_name}(data=__UNSET, *, usedforsecurity=True, string=__UNSET):
+ if data is __UNSET and string is not __UNSET:
+ import warnings
+ warnings.warn(
+ "the 'string' keyword parameter is deprecated since "
+ "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",
+ DeprecationWarning, stacklevel=2)
+ if data is not __UNSET and string is not __UNSET:
+ raise TypeError("'data' and 'string' are mutually exclusive "
+ "and support for 'string' keyword parameter "
+ "is slated for removal in a future version.")
+ raise ValueError("unsupported hash algorithm {__func_name}")
+'''
+ exec(__code, {"__UNSET": object()}, __locals := {})
+ globals()[__func_name] = __locals[__func_name]
+ del __exc, __code, __locals
# Cleanup locals()
del __always_supported, __func_name, __get_hash
del __py_new, __hash_new, __get_openssl_constructor
+del __logging
diff --git
a/Misc/NEWS.d/next/Library/2025-07-21-16-13-20.gh-issue-136929.obKZ2S.rst
b/Misc/NEWS.d/next/Library/2025-07-21-16-13-20.gh-issue-136929.obKZ2S.rst
new file mode 100644
index 00000000000000..31b8563f9d8523
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-07-21-16-13-20.gh-issue-136929.obKZ2S.rst
@@ -0,0 +1,5 @@
+Ensure that hash functions guaranteed to be always *available* exist as
+attributes of :mod:`hashlib` even if they will not work at runtime due to
+missing backend implementations. For instance, ``hashlib.md5`` will no
+longer raise :exc:`AttributeError` if OpenSSL is not available and Python
+has been built without MD5 support. Patch by Bénédikt Tran.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]