##// END OF EJS Templates
Hooks now implement "Chain of Command" design pattern,...
vivainio -
Show More
@@ -32,7 +32,7 b" ip_set_hook('editor',myiphooks.calljed)"
32 32 The ip_set_hook function is put by IPython into the builtin namespace, so it
33 33 is always available from all running code.
34 34
35 $Id: hooks.py 988 2006-01-02 21:21:47Z fperez $"""
35 $Id: hooks.py 1019 2006-01-14 13:02:12Z vivainio $"""
36 36
37 37 #*****************************************************************************
38 38 # Copyright (C) 2005 Fernando Perez. <fperez@colorado.edu>
@@ -46,7 +46,7 b" __author__ = '%s <%s>' % Release.authors['Fernando']"
46 46 __license__ = Release.license
47 47 __version__ = Release.version
48 48
49 import os
49 import os,bisect
50 50
51 51 # List here all the default hooks. For now it's just the editor functions
52 52 # but over time we'll move here all the public API for user-accessible things.
@@ -93,3 +93,44 b' def fix_error_editor(self,filename,linenum,column,msg):'
93 93 os.system('vim --cmd "set errorformat=%f:%l:%c:%m" -q ' + t.name)
94 94 finally:
95 95 t.close()
96
97 class TryNext(Exception):
98 pass
99
100 class CommandChainDispatcher:
101 """ Dispatch calls to a chain of commands until some func can handle it
102
103 Usage: instantiate, execute "add" to add commands (with optional
104 priority), execute normally via f() calling mechanism.
105
106 """
107 def __init__(self,commands=None):
108 if commands is None:
109 self.chain = []
110 else:
111 self.chain = commands
112
113
114 def __call__(self,*args, **kw):
115 """ Command chain is called just like normal func.
116
117 This will call all funcs in chain with the same args as were given to this
118 function, and return the result of first func that didn't raise
119 TryNext """
120
121 for prio,cmd in self.chain:
122 #print "prio",prio,"cmd",cmd #dbg
123 try:
124 ret = cmd(*args, **kw)
125 return ret
126 except TryNext:
127 pass
128
129 def __str__(self):
130 return str(self.chain)
131
132 def add(self, func, priority=0):
133 """ Add a func to the cmd chain with given priority """
134 bisect.insort(self.chain,(priority,func))
135
136 No newline at end of file
@@ -90,8 +90,9 b' def expose_magic(magicname, func):'
90 90 '''
91 91
92 92 from IPython import Magic
93
94 setattr(Magic.Magic, "magic_" + magicname, func)
93 import new
94 im = new.instancemethod(func,__IP, __IP.__class__)
95 setattr(__IP, "magic_" + magicname, im)
95 96
96 97 class asmagic:
97 98 """ Decorator for exposing magics in a friendly 2.4 decorator form
@@ -121,11 +122,12 b' class ashook:'
121 122
122 123 """
123 124
124 def __init__(self,name):
125 def __init__(self,name,priority=50):
125 126 self.name = name
127 self.prio = priority
126 128
127 129 def __call__(self,f):
128 set_hook(self.name, f)
130 set_hook(self.name, f, self.prio)
129 131 return f
130 132
131 133
@@ -6,7 +6,7 b' Requires Python 2.3 or newer.'
6 6
7 7 This file contains all the classes and helper functions specific to IPython.
8 8
9 $Id: iplib.py 1017 2006-01-14 09:46:45Z vivainio $
9 $Id: iplib.py 1019 2006-01-14 13:02:12Z vivainio $
10 10 """
11 11
12 12 #*****************************************************************************
@@ -401,7 +401,8 b' class InteractiveShell(object,Magic):'
401 401 # Set all default hooks, defined in the IPython.hooks module.
402 402 hooks = IPython.hooks
403 403 for hook_name in hooks.__all__:
404 self.set_hook(hook_name,getattr(hooks,hook_name))
404 # default hooks have priority 100, i.e. low; user hooks should have 0-100 priority
405 self.set_hook(hook_name,getattr(hooks,hook_name), 100)
405 406
406 407 # Flag to mark unconditional exit
407 408 self.exit_now = False
@@ -707,17 +708,31 b' class InteractiveShell(object,Magic):'
707 708 __builtin__.__dict__[biname] = bival
708 709 self.builtins_added.clear()
709 710
710 def set_hook(self,name,hook):
711 def set_hook(self,name,hook, priority = 50):
711 712 """set_hook(name,hook) -> sets an internal IPython hook.
712 713
713 714 IPython exposes some of its internal API as user-modifiable hooks. By
714 resetting one of these hooks, you can modify IPython's behavior to
715 call at runtime your own routines."""
715 adding your function to one of these hooks, you can modify IPython's
716 behavior to call at runtime your own routines."""
716 717
717 718 # At some point in the future, this should validate the hook before it
718 719 # accepts it. Probably at least check that the hook takes the number
719 720 # of args it's supposed to.
720 setattr(self.hooks,name,new.instancemethod(hook,self,self.__class__))
721 dp = getattr(self.hooks, name, None)
722 if not dp:
723 dp = IPython.hooks.CommandChainDispatcher()
724
725 f = new.instancemethod(hook,self,self.__class__)
726 try:
727 dp.add(f,priority)
728 except AttributeError:
729 # it was not commandchain, plain old func - replace
730 dp = f
731
732 setattr(self.hooks,name, dp)
733
734
735 #setattr(self.hooks,name,new.instancemethod(hook,self,self.__class__))
721 736
722 737 def set_custom_exc(self,exc_tuple,handler):
723 738 """set_custom_exc(exc_tuple,handler)
@@ -9,6 +9,12 b''
9 9 backslash (as yielded by tab completer) is still space;
10 10 "%cd long\ name" works as expected.
11 11
12 * IPython/ipapi.py,hooks.py,iplib.py: Hooks now implemented
13 as "chain of command", with priority. API stays the same,
14 TryNext exception raised by a hook function signals that
15 current hook failed and next hook should try handling it, as
16 suggested by Walter Dörwald <walter@livinglogic.de>.
17
12 18
13 19 2006-01-13 Ville Vainio <vivainio@gmail.com>
14 20
General Comments 0
You need to be logged in to leave comments. Login now