Commits

Mikhail Korobov committed 894d397

Python modules also can be Slackers

  • Participants
  • Parent commits b27d1d0

Comments (0)

Files changed (3)

 ========
 
 Slackers are special objects that are collecting operations (attribute
-access, calls, slicing) without actually executing them. Callable arguments
+access, calls, slicing) without actually executing them. Callables arguments
 must be picklable. Slackers also provide a method to apply the collected
 operations to a base object.
 
     def on_result(results):
         print results
 
+Python modules also can be Slackers::
+
+    import shutil
+    from slacker import Slacker
+    from slacker.workers import ThreadWorker
+
+    shutil_async = Slacker(shutil, ThreadWorker)
+    op = shutil_async.copy('file1.txt', 'file2.txt')
+    op.proceed()
 
 Workers
 =======

File slacker/postpone.py

 import pprint
+import sys
+import types
 try:
     import cPickle as pickle
 except ImportError:
 class SlackerException(Exception):
     pass
 
+class _Module(object):
+    """ Helper class for pickling python modules """
+
+    def __init__(self, module):
+        self.module = module
+
+    def __getstate__(self):
+        return self.module.__name__
+
+    def __setstate__(self, name):
+        __import__(name)
+        self.module = sys.modules[name]
+
 
 class Postponed(object):
     """
         return "%s: %s" % (self._obj, pprint.pformat(self._chain))
 
     def __getstate__(self):
+
+        if isinstance(self._obj, types.ModuleType):
+            return self._chain, _Module(self._obj)
+
         return self._chain, self._obj
 
     def __setstate__(self, state):
         self._chain, self._obj = state
+
+        if isinstance(self._obj, _Module):
+            self._obj = self._obj.module
+
         # always use local worker after unpickling
         self._worker = DummyWorker()
 

File slacker/tests.py

         self.assertEqual(chain._proceed().name, 'bar')
 
 
+class ModulesTest(unittest.TestCase):
+
+    def assertRepickled(self, chain, value):
+        repickled = pickle.loads(chain._pickled)
+        self.assertEqual(repickled._proceed(), value)
+
+    def test_modules(self):
+        import string
+        chain = Postponed(string).ascii_letters
+        self.assertEqual(chain._proceed(), string.ascii_letters)
+
+    def test_module_pickling_simple(self):
+        import string
+        chain = Postponed(string).ascii_letters
+        self.assertRepickled(chain, string.ascii_letters)
+
+    def test_module_pickling_dotted(self):
+        import logging.handlers
+        chain = Postponed(logging.handlers).SocketHandler
+        self.assertRepickled(chain, logging.handlers.SocketHandler)
+
+    def test_module_pickling_renamed(self):
+        from logging import handlers as hh
+        chain = Postponed(hh).SocketHandler
+        self.assertRepickled(chain, hh.SocketHandler)
+
+    def test_slacker(self):
+        from logging import handlers as hh
+        handlers = Slacker(hh)
+        self.assertRepickled(handlers.SocketHandler, hh.SocketHandler)
+        self.assertRepickled(handlers.DatagramHandler, hh.DatagramHandler)