@@ -261,16 +261,42 @@ def file_digest(fileobj, digest, /, *, _bufsize=2**18):
261
261
return digestobj
262
262
263
263
264
+ __logging = None
265
+ __logger = None
264
266
for __func_name in __always_supported :
265
267
# try them all, some may not work due to the OpenSSL
266
268
# version not supporting that algorithm.
267
269
try :
268
270
globals ()[__func_name ] = __get_hash (__func_name )
269
271
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
273
298
274
299
# Cleanup locals()
275
300
del __always_supported , __func_name , __get_hash
276
301
del __py_new , __hash_new , __get_openssl_constructor
302
+ del __logger , __logging
0 commit comments