@@ -261,16 +261,42 @@ def file_digest(fileobj, digest, /, *, _bufsize=2**18):
261261 return digestobj
262262
263263
264+ __logging = None
265+ __logger = None
264266for __func_name in __always_supported :
265267 # try them all, some may not work due to the OpenSSL
266268 # version not supporting that algorithm.
267269 try :
268270 globals ()[__func_name ] = __get_hash (__func_name )
269271 except ValueError :
270- import logging
271- logging .exception ('code for hash %s was not found.' , __func_name )
272-
272+ import logging as __logging
273+ if __logger is None :
274+ __logger = __logging .getLogger (__name__ )
275+ __logger .warning ('hash algorithm %s will not be supported at runtime' ,
276+ __func_name )
277+ # The following code can be simplified in Python 3.19
278+ # once "string" is removed from the signature.
279+ __code = f'''\
280+ def { __func_name } (data=__UNSET, *, usedforsecurity=True, string=__UNSET):
281+ if data is __UNSET and string is not __UNSET:
282+ import warnings
283+ warnings.warn(
284+ "the 'string' keyword parameter is deprecated since "
285+ "Python 3.15 and slated for removal in Python 3.19; "
286+ "use the 'data' keyword parameter or pass the data "
287+ "to hash as a positional argument instead",
288+ DeprecationWarning, stacklevel=2)
289+ if data is not __UNSET and string is not __UNSET:
290+ raise TypeError("'data' and 'string' are mutually exclusive "
291+ "and support for 'string' keyword parameter "
292+ "is slated for removal in a future version.")
293+ raise ValueError("unsupported hash algorithm { __func_name } ")
294+ '''
295+ exec (__code , {"__UNSET" : object ()}, __locals := {})
296+ globals ()[__func_name ] = __locals [__func_name ]
297+ del __code , __locals
273298
274299# Cleanup locals()
275300del __always_supported , __func_name , __get_hash
276301del __py_new , __hash_new , __get_openssl_constructor
302+ del __logger , __logging
0 commit comments