Dispatch calls to a chain of commands until some func can handle it Usage: instantiate, execute "add" to add commands (with optional priority), execute normally via f() calling mechanism.
| 87 | |
| 88 | |
| 89 | class CommandChainDispatcher: |
| 90 | """ Dispatch calls to a chain of commands until some func can handle it |
| 91 | |
| 92 | Usage: instantiate, execute "add" to add commands (with optional |
| 93 | priority), execute normally via f() calling mechanism. |
| 94 | |
| 95 | """ |
| 96 | def __init__(self,commands=None): |
| 97 | if commands is None: |
| 98 | self.chain = [] |
| 99 | else: |
| 100 | self.chain = commands |
| 101 | |
| 102 | |
| 103 | def __call__(self,*args, **kw): |
| 104 | """ Command chain is called just like normal func. |
| 105 | |
| 106 | This will call all funcs in chain with the same args as were given to |
| 107 | this function, and return the result of first func that didn't raise |
| 108 | TryNext""" |
| 109 | last_exc = TryNext() |
| 110 | for prio,cmd in self.chain: |
| 111 | #print "prio",prio,"cmd",cmd #dbg |
| 112 | try: |
| 113 | return cmd(*args, **kw) |
| 114 | except TryNext as exc: |
| 115 | last_exc = exc |
| 116 | # if no function will accept it, raise TryNext up to the caller |
| 117 | raise last_exc |
| 118 | |
| 119 | def __str__(self): |
| 120 | return str(self.chain) |
| 121 | |
| 122 | def add(self, func, priority=0): |
| 123 | """ Add a func to the cmd chain with given priority """ |
| 124 | self.chain.append((priority, func)) |
| 125 | self.chain.sort(key=lambda x: x[0]) |
| 126 | |
| 127 | def __iter__(self): |
| 128 | """ Return all objects in chain. |
| 129 | |
| 130 | Handy if the objects are not callable. |
| 131 | """ |
| 132 | return iter(self.chain) |
| 133 | |
| 134 | |
| 135 | def shutdown_hook(self): |
no outgoing calls