[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