Permalink
Browse files

Python modules also can be Slackers

  • Loading branch information...
1 parent 851cd1c commit c72ebc77e323fa5aa3512ee2a53f531e0eee3e40 @kmike committed Apr 29, 2011
Showing with 64 additions and 1 deletion.
  1. +10 −1 README.rst
  2. +23 −0 slacker/postpone.py
  3. +31 −0 slacker/tests.py
View
11 README.rst
@@ -47,7 +47,7 @@ Slackers
========
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.
@@ -77,6 +77,15 @@ be wrapped into Slacker, e.g.::
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
=======
View
23 slacker/postpone.py
@@ -1,4 +1,6 @@
import pprint
+import sys
+import types
try:
import cPickle as pickle
except ImportError:
@@ -10,6 +12,19 @@
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):
"""
@@ -34,10 +49,18 @@ def __repr__(self):
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()
View
31 slacker/tests.py
@@ -72,3 +72,34 @@ def test_top_level_callables(self):
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)

0 comments on commit c72ebc7

Please sign in to comment.