5
5
import inspect
6
6
import unittest
7
7
import unittest .mock
8
- from functools import partial
9
8
from test .support import import_helper
10
9
from types import MappingProxyType
11
10
@@ -207,7 +206,7 @@ def _chain_decorators(decorators):
207
206
"""
208
207
def decorator_func (func ):
209
208
return functools .reduce (lambda w , deco : deco (w ), decorators , func )
210
- return partial (_decorate_func_or_class , decorator_func )
209
+ return functools . partial (_decorate_func_or_class , decorator_func )
211
210
212
211
213
212
def _ensure_wrapper_signature (wrapper , wrapped ):
@@ -257,22 +256,22 @@ def _hashlib_new(digestname, openssl, /, **kwargs):
257
256
If *openssl* is True, module is "_hashlib" (C extension module),
258
257
otherwise it is "hashlib" (pure Python interface).
259
258
260
- The constructor function is returned, or SkipTest is raised if none exists.
259
+ The constructor function is returned (without binding **kwargs),
260
+ or SkipTest is raised if none exists.
261
261
"""
262
262
assert isinstance (digestname , str ), digestname
263
263
# Re-import 'hashlib' in case it was mocked, but propagate
264
264
# exceptions as it should be unconditionally available.
265
265
hashlib = importlib .import_module ("hashlib" )
266
266
# re-import '_hashlib' in case it was mocked
267
267
_hashlib = try_import_module ("_hashlib" )
268
- mod = _hashlib if openssl and _hashlib is not None else hashlib
269
- constructor = partial (mod .new , digestname , ** kwargs )
268
+ module = _hashlib if openssl and _hashlib is not None else hashlib
270
269
try :
271
- constructor ( )
270
+ module . new ( digestname , ** kwargs )
272
271
except ValueError :
273
- interface = f"{ mod .__name__ } .{ new . __name__ } "
272
+ interface = f"{ module .__name__ } .new"
274
273
raise SkipNoHash (digestname , interface = interface ) from exc
275
- return constructor
274
+ return functools . partial ( module . new , digestname )
276
275
277
276
278
277
def _builtin_hash (module_name , digestname , / , ** kwargs ):
@@ -304,26 +303,27 @@ def _builtin_hash(module_name, digestname, /, **kwargs):
304
303
def _openssl_new (digestname , / , ** kwargs ):
305
304
"""Check availability of _hashlib.new(digestname, **kwargs).
306
305
307
- The constructor function is returned, or SkipTest is raised if none exists.
306
+ The constructor function is returned (without binding **kwargs),
307
+ or SkipTest is raised if none exists.
308
308
"""
309
309
assert isinstance (digestname , str ), digestname
310
310
try :
311
311
# re-import '_hashlib' in case it was mocked
312
312
_hashlib = importlib .import_module ("_hashlib" )
313
313
except ImportError as exc :
314
314
raise SkipNoHash (digestname , "openssl" ) from exc
315
- constructor = partial (_hashlib .new , digestname , ** kwargs )
316
315
try :
317
- constructor ( )
316
+ _hashlib . new ( digestname , ** kwargs )
318
317
except ValueError as exc :
319
318
raise SkipNoHash (digestname , interface = "_hashlib.new" ) from exc
320
- return constructor
319
+ return functools . partial ( _hashlib . new , digestname )
321
320
322
321
323
322
def _openssl_hash (digestname , / , ** kwargs ):
324
323
"""Check availability of _hashlib.openssl_<digestname>(**kwargs).
325
324
326
- The constructor function is returned, or SkipTest is raised if none exists.
325
+ The constructor function is returned (without binding **kwargs),
326
+ or SkipTest is raised if none exists.
327
327
"""
328
328
assert isinstance (digestname , str ), digestname
329
329
fullname = f"_hashlib.openssl_{ digestname } "
@@ -350,7 +350,7 @@ def wrapper(*args, **kwargs):
350
350
test (* test_args , ** test_kwargs )
351
351
return func (* args , ** kwargs )
352
352
return wrapper
353
- return partial (_decorate_func_or_class , decorator_func )
353
+ return functools . partial (_decorate_func_or_class , decorator_func )
354
354
355
355
356
356
def requires_hashdigest (digestname , openssl = None , * , usedforsecurity = True ):
@@ -430,7 +430,9 @@ class HashFunctionsTrait:
430
430
'sha3_224' , 'sha3_256' , 'sha3_384' , 'sha3_512' ,
431
431
]
432
432
433
- # Default 'usedforsecurity' to use when looking up a hash function.
433
+ # Default 'usedforsecurity' to use when checking a hash function.
434
+ # When the trait properties are callables (e.g., _md5.md5) and
435
+ # not strings, they must be called with the same 'usedforsecurity'.
434
436
usedforsecurity = True
435
437
436
438
@classmethod
@@ -549,46 +551,55 @@ def find_gil_minsize(modules_names, default=2048):
549
551
def _block_openssl_hash_new (blocked_name ):
550
552
"""Block OpenSSL implementation of _hashlib.new()."""
551
553
assert isinstance (blocked_name , str ), blocked_name
554
+
552
555
# re-import '_hashlib' in case it was mocked
553
556
if (_hashlib := try_import_module ("_hashlib" )) is None :
554
557
return contextlib .nullcontext ()
558
+
555
559
@functools .wraps (wrapped := _hashlib .new )
556
- def wrapper (name , data = b'' , * , usedforsecurity = True , string = None ):
560
+ def _hashlib_new (name , data = b'' , * , usedforsecurity = True , string = None ):
557
561
if name == blocked_name :
558
562
raise _hashlib .UnsupportedDigestmodError (blocked_name )
559
563
return wrapped (* args , ** kwargs )
560
- _ensure_wrapper_signature (wrapper , wrapped )
561
- return unittest .mock .patch ('_hashlib.new' , wrapper )
564
+
565
+ _ensure_wrapper_signature (_hashlib_new , wrapped )
566
+ return unittest .mock .patch ('_hashlib.new' , _hashlib_new )
562
567
563
568
564
569
def _block_openssl_hmac_new (blocked_name ):
565
570
"""Block OpenSSL HMAC-HASH implementation."""
566
571
assert isinstance (blocked_name , str ), blocked_name
572
+
567
573
# re-import '_hashlib' in case it was mocked
568
574
if (_hashlib := try_import_module ("_hashlib" )) is None :
569
575
return contextlib .nullcontext ()
576
+
570
577
@functools .wraps (wrapped := _hashlib .hmac_new )
571
578
def wrapper (key , msg = b'' , digestmod = None ):
572
579
if digestmod == blocked_name :
573
580
raise _hashlib .UnsupportedDigestmodError (blocked_name )
574
581
return wrapped (key , msg , digestmod )
582
+
575
583
_ensure_wrapper_signature (wrapper , wrapped )
576
584
return unittest .mock .patch ('_hashlib.hmac_new' , wrapper )
577
585
578
586
579
587
def _block_openssl_hmac_digest (blocked_name ):
580
588
"""Block OpenSSL HMAC-HASH one-shot digest implementation."""
581
589
assert isinstance (blocked_name , str ), blocked_name
590
+
582
591
# re-import '_hashlib' in case it was mocked
583
592
if (_hashlib := try_import_module ("_hashlib" )) is None :
584
593
return contextlib .nullcontext ()
594
+
585
595
@functools .wraps (wrapped := _hashlib .hmac_digest )
586
- def wrapper (key , msg , digest ):
596
+ def _hashlib_hmac_digest (key , msg , digest ):
587
597
if digest == blocked_name :
588
598
raise _hashlib .UnsupportedDigestmodError (blocked_name )
589
599
return wrapped (key , msg , digestmod )
590
- _ensure_wrapper_signature (wrapper , wrapped )
591
- return unittest .mock .patch ('_hashlib.hmac_digest' , wrapper )
600
+
601
+ _ensure_wrapper_signature (_hashlib_hmac_digest , wrapped )
602
+ return unittest .mock .patch ('_hashlib.hmac_digest' , _hashlib_hmac_digest )
592
603
593
604
594
605
def _block_builtin_hash_new (name ):
@@ -610,6 +621,7 @@ def _block_builtin_hash_new(name):
610
621
get_builtin_constructor = getattr (hashlib , '__get_builtin_constructor' )
611
622
builtin_module_name = _EXPLICIT_CONSTRUCTORS [name ].builtin_module_name
612
623
624
+ @functools .wraps (get_builtin_constructor )
613
625
def get_builtin_constructor_mock (name ):
614
626
with import_helper .isolated_modules ():
615
627
sys = importlib .import_module ("sys" )
@@ -625,30 +637,36 @@ def get_builtin_constructor_mock(name):
625
637
626
638
def _block_builtin_hmac_new (blocked_name ):
627
639
assert isinstance (blocked_name , str ), blocked_name
640
+
628
641
# re-import '_hmac' in case it was mocked
629
642
if (_hmac := try_import_module ("_hmac" )) is None :
630
643
return contextlib .nullcontext ()
644
+
631
645
@functools .wraps (wrapped := _hmac .new )
632
- def wrapper (key , msg = None , digestmod = None ):
646
+ def _hmac_new (key , msg = None , digestmod = None ):
633
647
if digestmod == blocked_name :
634
648
raise _hmac .UnknownHashError (blocked_name )
635
649
return wrapped (key , msg , digestmod )
636
- _ensure_wrapper_signature (wrapper , wrapped )
637
- return unittest .mock .patch ('_hmac.new' , wrapper )
650
+
651
+ _ensure_wrapper_signature (_hmac_new , wrapped )
652
+ return unittest .mock .patch ('_hmac.new' , _hmac_new )
638
653
639
654
640
655
def _block_builtin_hmac_digest (blocked_name ):
641
656
assert isinstance (blocked_name , str ), blocked_name
657
+
642
658
# re-import '_hmac' in case it was mocked
643
659
if (_hmac := try_import_module ("_hmac" )) is None :
644
660
return contextlib .nullcontext ()
661
+
645
662
@functools .wraps (wrapped := _hmac .compute_digest )
646
- def wrapper (key , msg , digest ):
663
+ def _hmac_compute_digest (key , msg , digest ):
647
664
if digest == blocked_name :
648
665
raise _hmac .UnknownHashError (blocked_name )
649
666
return wrapped (key , msg , digest )
650
- _ensure_wrapper_signature (wrapper , wrapped )
651
- return unittest .mock .patch ('_hmac.compute_digest' , wrapper )
667
+
668
+ _ensure_wrapper_signature (_hmac_compute_digest , wrapped )
669
+ return unittest .mock .patch ('_hmac.compute_digest' , _hmac_compute_digest )
652
670
653
671
654
672
def _make_hash_constructor_blocker (name , dummy , implementation ):
0 commit comments