A naive attempt fails miserably:
import hashlib
class fred(hashlib.sha256):
pass
-> TypeError: Error when calling the metaclass bases
cannot create 'builtin_function_or_method' instances
Well, it turns out that hashlib.sha256 is a callable, not a class. Trying something a bit more creative doesn't work either:
import hashlib
class fred(type(hashlib.sha256())):
pass
f = fred
-> TypeError: cannot create 'fred' instances
Hmmm...
So, how do I do it?
Here is what I want to actually achieve:
class shad_256(sha256):
"""Double SHA - sha256(sha256(data).digest())
Less susceptible to length extension attacks than sha256 alone."""
def digest(self):
return sha256(sha256.digest(self)).digest()
def hexdigest(self):
return sha256(sha256.digest(self)).hexdigest()
Basically I want everything to pass through except when someone calls for a result I want to insert an extra step of my own. Is there a clever way I can accomplish this with __new__
or metaclass magic of some sort?
I have a solution I'm largely happy with that I posted as an answer, but I'm really interested to see if anybody can think of anything better. Either much less verbose with very little cost in readability or much faster (particularly when calling update
) while still being somewhat readable.
Update: I ran some tests:
# test_sha._timehash takes three parameters, the hash object generator to use,
# the number of updates and the size of the updates.
# Built in hashlib.sha256
$ python2.7 -m timeit -n 100 -s 'import test_sha, hashlib' 'test_sha._timehash(hashlib.sha256, 20000, 512)'
100 loops, best of 3: 104 msec per loop
# My wrapper based approach (see my answer)
$ python2.7 -m timeit -n 100 -s 'import test_sha, hashlib' 'test_sha._timehash(test_sha.wrapper_shad_256, 20000, 512)'
100 loops, best of 3: 108 msec per loop
# Glen Maynard's getattr based approach
$ python2.7 -m timeit -n 100 -s 'import test_sha, hashlib' 'test_sha._timehash(test_sha.getattr_shad_256, 20000, 512)'
100 loops, best of 3: 103 msec per loop