Issue #18742: Rework the internal hashlib construtor to pave the road for ABCs.

This commit is contained in:
Christian Heimes 2013-10-22 14:59:12 +02:00
parent 086b1afa55
commit e53510726b
2 changed files with 43 additions and 33 deletions

View file

@ -64,43 +64,42 @@ __all__ = __always_supported + ('new', 'algorithms_guaranteed',
'algorithms_available', 'pbkdf2_hmac') 'algorithms_available', 'pbkdf2_hmac')
__builtin_constructor_cache = {}
def __get_builtin_constructor(name): def __get_builtin_constructor(name):
cache = __builtin_constructor_cache
constructor = cache.get(name)
if constructor is not None:
return constructor
try: try:
if name in ('SHA1', 'sha1'): if name in ('SHA1', 'sha1'):
import _sha1 import _sha1
return _sha1.sha1 cache['SHA1'] = cache['sha1'] = _sha1.sha1
elif name in ('MD5', 'md5'): elif name in ('MD5', 'md5'):
import _md5 import _md5
return _md5.md5 cache['MD5'] = cache['md5'] = _md5.md5
elif name in ('SHA256', 'sha256', 'SHA224', 'sha224'): elif name in ('SHA256', 'sha256', 'SHA224', 'sha224'):
import _sha256 import _sha256
bs = name[3:] cache['SHA224'] = cache['sha224'] = _sha256.sha224
if bs == '256': cache['SHA256'] = cache['sha256'] = _sha256.sha256
return _sha256.sha256
elif bs == '224':
return _sha256.sha224
elif name in ('SHA512', 'sha512', 'SHA384', 'sha384'): elif name in ('SHA512', 'sha512', 'SHA384', 'sha384'):
import _sha512 import _sha512
bs = name[3:] cache['SHA384'] = cache['sha384'] = _sha512.sha384
if bs == '512': cache['SHA512'] = cache['sha512'] = _sha512.sha512
return _sha512.sha512
elif bs == '384':
return _sha512.sha384
elif name in {'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512', elif name in {'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512',
'SHA3_224', 'SHA3_256', 'SHA3_384', 'SHA3_512'}: 'SHA3_224', 'SHA3_256', 'SHA3_384', 'SHA3_512'}:
import _sha3 import _sha3
bs = name[5:] cache['SHA3_224'] = cache['sha3_224'] = _sha3.sha3_224
if bs == '224': cache['SHA3_256'] = cache['sha3_256'] = _sha3.sha3_256
return _sha3.sha3_224 cache['SHA3_384'] = cache['sha3_384'] = _sha3.sha3_384
elif bs == '256': cache['SHA3_512'] = cache['sha3_512'] = _sha3.sha3_512
return _sha3.sha3_256
elif bs == '384':
return _sha3.sha3_384
elif bs == '512':
return _sha3.sha3_512
except ImportError: except ImportError:
pass # no extension module, this hash is unsupported. pass # no extension module, this hash is unsupported.
constructor = cache.get(name)
if constructor is not None:
return constructor
raise ValueError('unsupported hash type ' + name) raise ValueError('unsupported hash type ' + name)

View file

@ -84,26 +84,30 @@ class HashLibTestCase(unittest.TestCase):
if constructor: if constructor:
constructors.add(constructor) constructors.add(constructor)
def add_builtin_constructor(name):
constructor = getattr(hashlib, "__get_builtin_constructor")(name)
self.constructors_to_test[name].add(constructor)
_md5 = self._conditional_import_module('_md5') _md5 = self._conditional_import_module('_md5')
if _md5: if _md5:
self.constructors_to_test['md5'].add(_md5.md5) add_builtin_constructor('md5')
_sha1 = self._conditional_import_module('_sha1') _sha1 = self._conditional_import_module('_sha1')
if _sha1: if _sha1:
self.constructors_to_test['sha1'].add(_sha1.sha1) add_builtin_constructor('sha1')
_sha256 = self._conditional_import_module('_sha256') _sha256 = self._conditional_import_module('_sha256')
if _sha256: if _sha256:
self.constructors_to_test['sha224'].add(_sha256.sha224) add_builtin_constructor('sha224')
self.constructors_to_test['sha256'].add(_sha256.sha256) add_builtin_constructor('sha256')
_sha512 = self._conditional_import_module('_sha512') _sha512 = self._conditional_import_module('_sha512')
if _sha512: if _sha512:
self.constructors_to_test['sha384'].add(_sha512.sha384) add_builtin_constructor('sha384')
self.constructors_to_test['sha512'].add(_sha512.sha512) add_builtin_constructor('sha512')
_sha3 = self._conditional_import_module('_sha3') _sha3 = self._conditional_import_module('_sha3')
if _sha3: if _sha3:
self.constructors_to_test['sha3_224'].add(_sha3.sha3_224) add_builtin_constructor('sha3_224')
self.constructors_to_test['sha3_256'].add(_sha3.sha3_256) add_builtin_constructor('sha3_256')
self.constructors_to_test['sha3_384'].add(_sha3.sha3_384) add_builtin_constructor('sha3_384')
self.constructors_to_test['sha3_512'].add(_sha3.sha3_512) add_builtin_constructor('sha3_512')
super(HashLibTestCase, self).__init__(*args, **kwargs) super(HashLibTestCase, self).__init__(*args, **kwargs)
@ -132,8 +136,10 @@ class HashLibTestCase(unittest.TestCase):
self.assertRaises(TypeError, hashlib.new, 1) self.assertRaises(TypeError, hashlib.new, 1)
def test_get_builtin_constructor(self): def test_get_builtin_constructor(self):
get_builtin_constructor = hashlib.__dict__[ get_builtin_constructor = getattr(hashlib,
'__get_builtin_constructor'] '__get_builtin_constructor')
builtin_constructor_cache = getattr(hashlib,
'__builtin_constructor_cache')
self.assertRaises(ValueError, get_builtin_constructor, 'test') self.assertRaises(ValueError, get_builtin_constructor, 'test')
try: try:
import _md5 import _md5
@ -141,6 +147,8 @@ class HashLibTestCase(unittest.TestCase):
pass pass
# This forces an ImportError for "import _md5" statements # This forces an ImportError for "import _md5" statements
sys.modules['_md5'] = None sys.modules['_md5'] = None
# clear the cache
builtin_constructor_cache.clear()
try: try:
self.assertRaises(ValueError, get_builtin_constructor, 'md5') self.assertRaises(ValueError, get_builtin_constructor, 'md5')
finally: finally:
@ -149,6 +157,9 @@ class HashLibTestCase(unittest.TestCase):
else: else:
del sys.modules['_md5'] del sys.modules['_md5']
self.assertRaises(TypeError, get_builtin_constructor, 3) self.assertRaises(TypeError, get_builtin_constructor, 3)
constructor = get_builtin_constructor('md5')
self.assertIs(constructor, _md5.md5)
self.assertEqual(sorted(builtin_constructor_cache), ['MD5', 'md5'])
def test_hexdigest(self): def test_hexdigest(self):
for cons in self.hash_constructors: for cons in self.hash_constructors: