Skip to content

Commit e535107

Browse files
committed
Issue #18742: Rework the internal hashlib construtor to pave the road for ABCs.
1 parent 086b1af commit e535107

File tree

2 files changed

+43
-33
lines changed

2 files changed

+43
-33
lines changed

Lib/hashlib.py

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -64,43 +64,42 @@
6464
'algorithms_available', 'pbkdf2_hmac')
6565

6666

67+
__builtin_constructor_cache = {}
68+
6769
def __get_builtin_constructor(name):
70+
cache = __builtin_constructor_cache
71+
constructor = cache.get(name)
72+
if constructor is not None:
73+
return constructor
6874
try:
6975
if name in ('SHA1', 'sha1'):
7076
import _sha1
71-
return _sha1.sha1
77+
cache['SHA1'] = cache['sha1'] = _sha1.sha1
7278
elif name in ('MD5', 'md5'):
7379
import _md5
74-
return _md5.md5
80+
cache['MD5'] = cache['md5'] = _md5.md5
7581
elif name in ('SHA256', 'sha256', 'SHA224', 'sha224'):
7682
import _sha256
77-
bs = name[3:]
78-
if bs == '256':
79-
return _sha256.sha256
80-
elif bs == '224':
81-
return _sha256.sha224
83+
cache['SHA224'] = cache['sha224'] = _sha256.sha224
84+
cache['SHA256'] = cache['sha256'] = _sha256.sha256
8285
elif name in ('SHA512', 'sha512', 'SHA384', 'sha384'):
8386
import _sha512
84-
bs = name[3:]
85-
if bs == '512':
86-
return _sha512.sha512
87-
elif bs == '384':
88-
return _sha512.sha384
87+
cache['SHA384'] = cache['sha384'] = _sha512.sha384
88+
cache['SHA512'] = cache['sha512'] = _sha512.sha512
8989
elif name in {'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512',
9090
'SHA3_224', 'SHA3_256', 'SHA3_384', 'SHA3_512'}:
9191
import _sha3
92-
bs = name[5:]
93-
if bs == '224':
94-
return _sha3.sha3_224
95-
elif bs == '256':
96-
return _sha3.sha3_256
97-
elif bs == '384':
98-
return _sha3.sha3_384
99-
elif bs == '512':
100-
return _sha3.sha3_512
92+
cache['SHA3_224'] = cache['sha3_224'] = _sha3.sha3_224
93+
cache['SHA3_256'] = cache['sha3_256'] = _sha3.sha3_256
94+
cache['SHA3_384'] = cache['sha3_384'] = _sha3.sha3_384
95+
cache['SHA3_512'] = cache['sha3_512'] = _sha3.sha3_512
10196
except ImportError:
10297
pass # no extension module, this hash is unsupported.
10398

99+
constructor = cache.get(name)
100+
if constructor is not None:
101+
return constructor
102+
104103
raise ValueError('unsupported hash type ' + name)
105104

106105

Lib/test/test_hashlib.py

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -84,26 +84,30 @@ def _test_algorithm_via_hashlib_new(data=None, _alg=algorithm):
8484
if constructor:
8585
constructors.add(constructor)
8686

87+
def add_builtin_constructor(name):
88+
constructor = getattr(hashlib, "__get_builtin_constructor")(name)
89+
self.constructors_to_test[name].add(constructor)
90+
8791
_md5 = self._conditional_import_module('_md5')
8892
if _md5:
89-
self.constructors_to_test['md5'].add(_md5.md5)
93+
add_builtin_constructor('md5')
9094
_sha1 = self._conditional_import_module('_sha1')
9195
if _sha1:
92-
self.constructors_to_test['sha1'].add(_sha1.sha1)
96+
add_builtin_constructor('sha1')
9397
_sha256 = self._conditional_import_module('_sha256')
9498
if _sha256:
95-
self.constructors_to_test['sha224'].add(_sha256.sha224)
96-
self.constructors_to_test['sha256'].add(_sha256.sha256)
99+
add_builtin_constructor('sha224')
100+
add_builtin_constructor('sha256')
97101
_sha512 = self._conditional_import_module('_sha512')
98102
if _sha512:
99-
self.constructors_to_test['sha384'].add(_sha512.sha384)
100-
self.constructors_to_test['sha512'].add(_sha512.sha512)
103+
add_builtin_constructor('sha384')
104+
add_builtin_constructor('sha512')
101105
_sha3 = self._conditional_import_module('_sha3')
102106
if _sha3:
103-
self.constructors_to_test['sha3_224'].add(_sha3.sha3_224)
104-
self.constructors_to_test['sha3_256'].add(_sha3.sha3_256)
105-
self.constructors_to_test['sha3_384'].add(_sha3.sha3_384)
106-
self.constructors_to_test['sha3_512'].add(_sha3.sha3_512)
107+
add_builtin_constructor('sha3_224')
108+
add_builtin_constructor('sha3_256')
109+
add_builtin_constructor('sha3_384')
110+
add_builtin_constructor('sha3_512')
107111

108112
super(HashLibTestCase, self).__init__(*args, **kwargs)
109113

@@ -132,15 +136,19 @@ def test_unknown_hash(self):
132136
self.assertRaises(TypeError, hashlib.new, 1)
133137

134138
def test_get_builtin_constructor(self):
135-
get_builtin_constructor = hashlib.__dict__[
136-
'__get_builtin_constructor']
139+
get_builtin_constructor = getattr(hashlib,
140+
'__get_builtin_constructor')
141+
builtin_constructor_cache = getattr(hashlib,
142+
'__builtin_constructor_cache')
137143
self.assertRaises(ValueError, get_builtin_constructor, 'test')
138144
try:
139145
import _md5
140146
except ImportError:
141147
pass
142148
# This forces an ImportError for "import _md5" statements
143149
sys.modules['_md5'] = None
150+
# clear the cache
151+
builtin_constructor_cache.clear()
144152
try:
145153
self.assertRaises(ValueError, get_builtin_constructor, 'md5')
146154
finally:
@@ -149,6 +157,9 @@ def test_get_builtin_constructor(self):
149157
else:
150158
del sys.modules['_md5']
151159
self.assertRaises(TypeError, get_builtin_constructor, 3)
160+
constructor = get_builtin_constructor('md5')
161+
self.assertIs(constructor, _md5.md5)
162+
self.assertEqual(sorted(builtin_constructor_cache), ['MD5', 'md5'])
152163

153164
def test_hexdigest(self):
154165
for cons in self.hash_constructors:

0 commit comments

Comments
 (0)