Commits

Christian Tismer committed f9773b6

a much cleaner implementation with a metaclass that injects methods into a different module

Comments (0)

Files changed (1)

tool/tiff_reader/tiffany/monkeypil.py

-import sys, os
+import sys, os, types, new
 
 """
 Tiffany - Tiff with PIL without PIL
     from tiffany import start_mapper
     start_mapper()
 
-from tiffany import Image
+from tiffany import Image, TiffImagePlugin
 
 class TiffanyCore:
     __module__ = 'Image.core'
         decoder """
         return self.TiffanyEncoder(mode, args)
 
+
+# a handy metaclass that injects a class into a different module
+class TiffanyMeta(type):
+    def __new__(_mcs, _name, _bases, _dict):
+        meth_globals = inject_into_module.__dict__
+        stmethodtype = type(staticmethod(lambda:None))
+        
+        def func_with_new_globals(func, globals):
+            """Make a copy of a function with new globals."""
+            f = new.function(func.func_code, globals,
+                             func.func_name, func.func_defaults,
+                             func.func_closure)
+            if func.func_dict:
+                f.func_dict = {}
+                f.func_dict.update(func.func_dict)
+            return f
+
+        for name, func in _dict.items():
+            if isinstance(func, (types.FunctionType, stmethodtype)):
+                replacing_method = None
+                if isinstance(func, stmethodtype):
+                    func = func.__func__
+                    replacing_method = staticmethod
+                func = func_with_new_globals(func, meth_globals)
+                if replacing_method:
+                    func = replacing_method(func)
+                _dict[name] = func
+        return type.__new__(_mcs, _name, _bases, _dict)
+
 Image.core = TiffanyCore()
+inject_into_module = TiffImagePlugin
 
-def monkey_patch():
+class TiffanyImageFile(TiffImagePlugin.TiffImageFile, object):
+    __metaclass__ = TiffanyMeta
     
-    from tiffany import Image, TiffImagePlugin
-
+    @staticmethod
     def _save_as_is(im, fp, filename):
+        import os
         try:
             rawmode, prefix, photo, format, bits, extra = SAVE_INFO[im.mode]
         except KeyError:
         # -- find ifd's link position --
         im.last_linkoffset = savepos + 2 + len(ifd.tags) * 12
         
-    _save_as_is.__globals__.update(TiffImagePlugin._save.__globals__)
-    TiffImagePlugin._save_as_is = _save_as_is
-    Image.register_save("TIFF", _save_as_is)
+Image.register_save("TIFF", TiffanyImageFile._save_as_is)
     
 def inline_test():
     imfile = os.path.join(rootpath, 'test/data/test_image.tiff')
+    outfile = os.path.join(os.path.dirname(imfile), 'look_page2.tiff')
     im = Image.open(imfile)
     
-    monkey_patch()
-    with file('look_page2.tiff', 'wb') as imf:
+    with file(outfile, 'wb') as imf:
         for i in range(5):
             im.seek(1)
             im.save(imf, 'tiff')