Commits

Anonymous committed fadd31e

Added Quick-and-Dirty Dispatch (qndispatch) to remove dependency RuleDispatch

  • Participants
  • Parent commits d49decb

Comments (0)

Files changed (4)

-import dispatch
+import qndispatch as dispatch
 
 class CodeGenException(Exception):
     pass

pygen/qndispatch/__init__.py

+
+from qndispatch import on
+

pygen/qndispatch/qndispatch.py

+
+import inspect
+
+class InvalidArgException(Exception):
+    pass
+
+class DispatchTargetException(Exception):
+    pass
+
+class Dispatcher(object):
+    '''General dispatcher object'''
+    def __init__(self, name, argnum, args):
+        self.name = name
+        self.argnum = argnum
+        self.args = args
+
+        self.functions = []
+
+    def get(self, args, kw):
+        '''Get function to dispatch to based on args and kw'''
+        if self.name in kw:
+            arg = kw[self.name]
+        else:
+            arg = args[self.argnum]
+
+        for reg_arg, reg_func in self.functions:
+            if isinstance(arg, reg_arg):
+                return reg_func
+
+        raise InvalidArgException("No function found.")
+
+    def register(self, func, arg):
+        '''Register a new function with the dispatcher'''
+        args = inspect.getargspec(func)
+        if args != self.args:
+            raise DispatchTargetException("Target arguments to not match with source.")
+
+        self.functions.append((arg, func))
+
+def on(name):
+    '''Dispatch on argument "name"'''
+    def on_decorate(func):
+        args = inspect.getargspec(func)
+        argnum = args.args.index(name)
+
+        dispatcher = Dispatcher(name, argnum, args)
+
+        def decorator(*args, **kw):
+            return dispatcher.get(args, kw)(*args, **kw)
+
+        def when(arg):
+            def when_decorate(func):
+                dispatcher.register(func, arg)
+                return decorator
+            
+            return when_decorate
+
+        decorator.when = when
+
+        return decorator
+
+    return on_decorate
+
+
+
+
+
+

pygen/qndispatch/tests.py

+import unittest
+
+import qndispatch
+
+class DispatchTest(unittest.TestCase):
+    def testDispatchOn(self):
+        class TestClass(object):
+
+            @qndispatch.on("name")
+            def test(self, name):
+                self.fail("Illegal call to dispatch.on function")
+                pass
+
+            @test.when(str)
+            def test(self, name):
+                pass
+
+        t = TestClass()
+        t.test("n")
+        t.test(name="n")
+
+        try:
+            t.test([])
+            self.fail("Dispatch with unregistered type did not fail.")
+        except qndispatch.InvalidArgException:
+            pass
+
+    def testTargetMismatch(self):
+        try:
+            class TestClass(object):
+
+                @qndispatch.on("name")
+                def test(self, name):
+                    self.fail("Illegal call to dispatch.on function")
+                    pass
+
+                @test.when(str)
+                def test(self, name, mismatch):
+                    pass
+            self.fail("Target argument mismatch not found.")
+        except qndispatch.DispatchTargetException:
+            pass
+
+
+if __name__ == "__main__":
+    #import sys;sys.argv = ['', 'Test.testName']
+    unittest.main()
+
+
+