Alexander Schremmer avatar Alexander Schremmer committed 74f1e74

Add example md5demo module.

Comments (0)

Files changed (6)

pypy/module/__init__.py

 # empty
+from pypy.module.md5demo import interp_md5
+from pypy.translator.sepcomp import scimport, ImportExportComponent, export
+
+ImportExportComponent("md5demo", interp_md5)

pypy/module/md5demo/__init__.py

+
+"""
+Mixed-module definition for the md5 module.
+Note that there is also a pure Python implementation in pypy/lib/md5.py;
+the present mixed-module version of md5 takes precedence if it is enabled.
+"""
+
+from pypy.interpreter.mixedmodule import MixedModule
+
+
+class Module(MixedModule):
+    """\
+This module implements the interface to RSA's MD5 message digest
+algorithm (see also Internet RFC 1321). Its use is quite
+straightforward: use new() to create an md5 object. You can now feed
+this object with arbitrary strings using the update() method, and at any
+point you can ask it for the digest (a strong kind of 128-bit checksum,
+a.k.a. ``fingerprint'') of the concatenation of the strings fed to it so
+far using the digest() method."""
+
+    interpleveldefs = {
+        'md5': 'interp_md5.W_MD5',
+        'new': 'interp_md5.W_MD5',
+        'MD5Type': 'interp_md5.W_MD5',
+        'digest_size': 'space.wrap(16)',
+        'load_module': 'interp_md5.load_module',
+        }
+
+    appleveldefs = {
+        }

pypy/module/md5demo/interface.py

+from pypy.translator.sepcomp import scimport
+from pypy.module.md5demo.interp_md5 import RMD5Interface
+
+MD5Interface = scimport(RMD5Interface)
+del RMD5Interface

pypy/module/md5demo/interp_md5.py

+from pypy.rlib import rmd5
+from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.typedef import TypeDef
+from pypy.interpreter.gateway import interp2app, ObjSpace, W_Root
+
+from pypy.rlib.objectmodel import instantiate, we_are_translated
+from pypy.translator.sepcomp import scimport, ImportExportComponent, export
+from pypy.rlib.libffi import dlopen_global_persistent
+
+
+class RMD5Interface(rmd5.RMD5):
+    _exported_ = True
+    @export
+    def _init(self):
+        rmd5.RMD5._init(self)
+        return 1
+
+    @export
+    def digest(self):
+        return rmd5.RMD5.digest(self)
+
+    @export(str)
+    def update(self, x):
+        return rmd5.RMD5.update(self, x)
+
+
+class W_MD5(Wrappable):
+    """
+    A subclass of RMD5 that can be exposed to app-level.
+    """
+
+    def __init__(self, space, md5obj):
+        self.space = space
+        self.md5obj = md5obj
+        md5obj._init()
+
+    def update_w(self, string):
+        self.md5obj.update(string)
+
+    def digest_w(self):
+        return self.space.wrap(self.md5obj.digest())
+
+    def hexdigest_w(self):
+        return self.space.wrap(self.md5obj.hexdigest())
+
+
+def W_MD5___new__(space, w_subtype, initialdata=''):
+    """
+    Create a new md5 object and call its initializer.
+    """
+    a = RMD5Interface() # hack
+    w_md5 = space.allocate_instance(W_MD5, w_subtype)
+    md5 = space.interp_w(W_MD5, w_md5)
+    W_MD5.__init__(md5, space, module_init())
+    md5.md5obj.update(initialdata)
+    return w_md5
+
+class MyRMD5(RMD5Interface):
+    def digest(self):
+        return RMD5Interface.digest(self) + "added string"
+
+def module_init():
+    return get_dynamic_object()
+    #return MyRMD5()
+
+@export(ret=RMD5Interface, force_name="module_init")
+def get_dynamic_object(foo):
+    raise NotImplementedError
+
+get_dynamic_object = scimport(get_dynamic_object, dynamic=True, forward_ref=True)
+
+
+
+def load_module(space):
+    dlopen_global_persistent("/tmp/testmodule.so")
+    return space.wrap(None)
+load_module.unwrap_spec = [ObjSpace]
+
+W_MD5.typedef = TypeDef(
+    'MD5Type',
+    __new__   = interp2app(W_MD5___new__, unwrap_spec=[ObjSpace, W_Root,
+                                                       'bufferstr']),
+    update    = interp2app(W_MD5.update_w, unwrap_spec=['self', 'bufferstr']),
+    digest    = interp2app(W_MD5.digest_w, unwrap_spec=['self']),
+    hexdigest = interp2app(W_MD5.hexdigest_w, unwrap_spec=['self']),
+    __doc__   = """md5(arg) -> return new md5 object.
+
+If arg is present, the method call update(arg) is made.""")

pypy/module/md5demo/module_md5.py

+from pypy.rlib import rmd5
+from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.typedef import TypeDef
+from pypy.interpreter.gateway import interp2app, ObjSpace, W_Root
+
+from pypy.rlib.objectmodel import instantiate, we_are_translated
+from pypy.translator.sepcomp import scimport, ImportExportComponent, export
+from pypy.rlib.libffi import dlopen_global_persistent
+
+class RMD5_interface(rmd5.RMD5):
+    pass
+class W_MD5(Wrappable):
+    """
+    A subclass of RMD5 that can be exposed to app-level.
+    """
+    _exported_ = True
+
+    def __init__(self, space):
+        self.space = space
+        self._init()
+
+    def update_w(self, string):
+        self.update(string)
+
+    @export
+    def _init(self):
+        return rmd5.RMD5._init(self)
+
+    @export
+    def digest(self):
+        return rmd5.RMD5.digest(self)
+
+    @export(str)
+    def update(self, x):
+        return rmd5.RMD5.update(self, x)
+
+    @export(W_Root)
+    def dostuff_w(self, w_arg):
+        return w_arg
+
+class W_MyMD5(W_MD5):
+    def __init__(self, spacewrapper):
+        self.spacewrapper = spacewrapper
+        self._init()
+    def digest(self):
+        return W_MD5.digest(self) + "added string"
+
+def module_init(spacewrapper, data):
+    w_mymd5 = instantiate(W_MyMD5)
+    if not we_are_translated():
+        w_mymd5.space = spacewrapper.space
+    w_mymd5.__init__(spacewrapper)
+    w_mymd5.update(data)
+    return w_mymd5
+
+@export(SpaceWrapper, str, ret=W_Root, force_name="module_init")
+def get_dynamic_object(foo):
+    raise NotImplementedError
+
+get_dynamic_object = scimport(get_dynamic_object, dynamic=True, forward_ref=True)
+
+
+def dynamic_md5(space, initialdata=""):
+    sw = SpaceWrapper(space)
+    w_obj = get_dynamic_object(sw, initialdata)
+    #w_obj = module_init(sw, initialdata)
+    return w_obj
+dynamic_md5.unwrap_spec = [ObjSpace, str]
+
+

pypy/module/md5demo/test/test_md5.py

+"""
+Tests for the md5 module implemented at interp-level in pypy/module/md5.
+"""
+
+import py
+from pypy.conftest import gettestobjspace
+
+
+class AppTestMD5DEMO(object):
+
+    def setup_class(cls):
+        """
+        Create a space with the md5 module and import it for use by the
+        tests.
+        """
+        cls.space = gettestobjspace(usemodules=['md5demo'])
+        cls.w_md5 = cls.space.appexec([], """():
+            import md5demo
+            return md5demo
+        """)
+
+    def test_dynamic(self):
+        import md5
+        assert self.md5.md5()
+        assert self.md5.md5("foo").digest() == md5.md5("foo").digest() + "added string"
+        self.md5.load_module()
+
+
+    def test_digest_size(self):
+        """
+        md5.digest_size should be 16.
+        """
+        assert self.md5.digest_size == 16
+
+
+    def test_MD5Type(self):
+        """
+        Test the two ways to construct an md5 object.
+        """
+        md5 = self.md5
+        d = md5.md5()
+        assert isinstance(d, md5.MD5Type)
+        d = md5.new()
+        assert isinstance(d, md5.MD5Type)
+
+
+    def test_md5object(self):
+        """
+        Feed example strings into a md5 object and check the digest and
+        hexdigest.
+        """
+        md5 = self.md5
+        cases = (
+          ("",
+           "d41d8cd98f00b204e9800998ecf8427e"),
+          ("a",
+           "0cc175b9c0f1b6a831c399e269772661"),
+          ("abc",
+           "900150983cd24fb0d6963f7d28e17f72"),
+          ("message digest",
+           "f96b697d7cb7938d525a2f31aaf161d0"),
+          ("abcdefghijklmnopqrstuvwxyz",
+           "c3fcd3d76192e4007dfb496cca67e13b"),
+          ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+           "d174ab98d277d9f5a5611c2c9f419d9f"),
+          ("1234567890"*8,
+           "57edf4a22be3c955ac49da2e2107b67a"),
+        )
+        for input, expected in cases:
+            d = md5.new(input)
+            assert d.hexdigest() == expected
+            assert d.digest() == expected.decode('hex')
+
+
+    def test_copy(self):
+        """
+        Test the copy() method.
+        """
+        md5 = self.md5
+        d1 = md5.md5()
+        d1.update("abcde")
+        d2 = d1.copy()
+        d2.update("fgh")
+        d1.update("jkl")
+        assert d1.hexdigest() == 'e570e7110ecef72fcb772a9c05d03373'
+        assert d2.hexdigest() == 'e8dc4081b13434b45189a720b77b6818'
+
+
+    def test_buffer(self):
+        """
+        Test passing a buffer object.
+        """
+        md5 = self.md5
+        d1 = md5.md5(buffer("abcde"))
+        d1.update(buffer("jkl"))
+        assert d1.hexdigest() == 'e570e7110ecef72fcb772a9c05d03373'
+
+
+    def test_unicode(self):
+        """
+        Test passing unicode strings.
+        """
+        md5 = self.md5
+        d1 = md5.md5(u"abcde")
+        d1.update(u"jkl")
+        assert d1.hexdigest() == 'e570e7110ecef72fcb772a9c05d03373'
+        raises(UnicodeEncodeError, d1.update, u'\xe9')
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.