Author: Amaury Forgeot d'Arc <amaur...@gmail.com> Branch: py3k Changeset: r48333:08ea3258278e Date: 2011-10-22 00:24 +0200 http://bitbucket.org/pypy/pypy/changeset/08ea3258278e/
Log: Implement _hashlib.openssl_md_meth_names, needed by hashlib.py diff --git a/pypy/module/_hashlib/__init__.py b/pypy/module/_hashlib/__init__.py --- a/pypy/module/_hashlib/__init__.py +++ b/pypy/module/_hashlib/__init__.py @@ -5,6 +5,7 @@ class Module(MixedModule): interpleveldefs = { 'new' : 'interp_hashlib.new', + 'openssl_md_meth_names': 'interp_hashlib.get(space).w_meth_names' } appleveldefs = { diff --git a/pypy/module/_hashlib/interp_hashlib.py b/pypy/module/_hashlib/interp_hashlib.py --- a/pypy/module/_hashlib/interp_hashlib.py +++ b/pypy/module/_hashlib/interp_hashlib.py @@ -12,6 +12,47 @@ algorithms = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512') +def hash_name_mapper_callback(obj_name, userdata): + state = global_state[0] + assert state is not None + if not obj_name: + return + # Ignore aliased names, they pollute the list and OpenSSL appears + # to have a its own definition of alias as the resulting list + # still contains duplicate and alternate names for several + # algorithms. + if obj_name[0].c_alias: + return + try: + w_name = state.space.wrap(rffi.charp2str(obj_name[0].c_name)) + state.space.call_method(state.w_meth_names, "add", w_name) + except OperationError, e: + state.w_error = e + +# XXX make it threadlocal? +global_state = [None] + +class State: + def __init__(self, space): + self.space = space + self.generate_method_names(space) + + def generate_method_names(self, space): + self.w_error = None + try: + global_state[0] = self + self.w_meth_names = space.call_function(space.w_set) + ropenssl.OBJ_NAME_do_all( + ropenssl.OBJ_NAME_TYPE_MD_METH, + hash_name_mapper_callback, None) + finally: + global_state[0] = None + if self.w_error: + raise self.w_error + +def get(space): + return space.fromcache(State) + class W_Hash(Wrappable): ctx = lltype.nullptr(ropenssl.EVP_MD_CTX.TO) diff --git a/pypy/module/_hashlib/test/test_hashlib.py b/pypy/module/_hashlib/test/test_hashlib.py --- a/pypy/module/_hashlib/test/test_hashlib.py +++ b/pypy/module/_hashlib/test/test_hashlib.py @@ -5,6 +5,11 @@ def setup_class(cls): cls.space = gettestobjspace(usemodules=['_hashlib']) + def test_method_names(self): + import _hashlib + assert isinstance(_hashlib.openssl_md_meth_names, set) + assert "md5" in _hashlib.openssl_md_meth_names + def test_simple(self): import _hashlib assert _hashlib.new('md5').__class__.__name__ == 'HASH' diff --git a/pypy/rlib/ropenssl.py b/pypy/rlib/ropenssl.py --- a/pypy/rlib/ropenssl.py +++ b/pypy/rlib/ropenssl.py @@ -89,6 +89,9 @@ CRYPTO_LOCK = rffi_platform.ConstantInteger("CRYPTO_LOCK") + OBJ_NAME_TYPE_MD_METH = rffi_platform.ConstantInteger( + "OBJ_NAME_TYPE_MD_METH") + # Some structures, with only the fields used in the _ssl module X509_name_entry_st = rffi_platform.Struct('struct X509_name_entry_st', [('set', rffi.INT)]) @@ -110,6 +113,12 @@ [('type', rffi.INT), ]) + OBJ_NAME_st = rffi_platform.Struct( + 'OBJ_NAME', + [('alias', rffi.INT), + ('name', rffi.CCHARP), + ]) + for k, v in rffi_platform.configure(CConfig).items(): globals()[k] = v @@ -130,6 +139,7 @@ ASN1_INTEGER = rffi.COpaquePtr('ASN1_INTEGER') GENERAL_NAMES = rffi.COpaquePtr('GENERAL_NAMES') GENERAL_NAME = rffi.CArrayPtr(GENERAL_NAME_st) +OBJ_NAME = rffi.CArrayPtr(OBJ_NAME_st) HAVE_OPENSSL_RAND = OPENSSL_VERSION_NUMBER >= 0x0090500f @@ -276,6 +286,11 @@ EVP_MD_CTX_cleanup = external( 'EVP_MD_CTX_cleanup', [EVP_MD_CTX], rffi.INT, threadsafe=False) +OBJ_NAME_CALLBACK = lltype.Ptr(lltype.FuncType( + [OBJ_NAME, rffi.VOIDP], lltype.Void)) +OBJ_NAME_do_all = external( + 'OBJ_NAME_do_all', [rffi.INT, OBJ_NAME_CALLBACK, rffi.VOIDP], lltype.Void) + def init_ssl(): libssl_SSL_load_error_strings() libssl_SSL_library_init() _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit