I'm casually reading Python module hashlib. From the doc I see I can use hashlib.md5() to call up md5. I wonder how that code works? In hashlib.py source code, it appears to me __get_builtin_constructor probably gets called with md5, but I don't know how the code works. Yes I can see md5 is defined for __all__ but how does it get there?
1 Answer
The key is here:
135 for __func_name in __always_supported:
136 # try them all, some may not work due to the OpenSSL
137 # version not supporting that algorithm.
138 try:
139 globals()[__func_name] = __get_hash(__func_name)
The __get_hash function maps to either __get_builtin_constructor or __get_openssl_constructor depending on the availability of openssl.
Let's assume openssl is not available. This is how it would look...
The for __func_name line would iterate the keys of
__always_supported = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512')
And would add a reference to each in the module scope (globals()). When you call hashlib.md5(), first it uses
66 def __get_builtin_constructor(name):
To define a callable which is returned. In the case of md5 it returns
73 return _md5.new
Since it is a callable that is returned, the call is then made because of the parenthesis after hashlib.md5.
4 Comments
__func_name is in the dictionary the globals() returns to __get_hash(__func_name). And when I say hashlib.md5() it goes to __get_hash?
globals()[..] = ....