[pypy-commit] pypy py3k: Implement _hashlib.openssl_md_meth_names, needed by hashlib.py

amauryfa noreply at buildbot.pypy.org
Sat Oct 22 00:28:41 CEST 2011


Author: Amaury Forgeot d'Arc <amauryfa at 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()


More information about the pypy-commit mailing list