##// 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 The ip_set_hook function is put by IPython into the builtin namespace, so it
32 The ip_set_hook function is put by IPython into the builtin namespace, so it
33 is always available from all running code.
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 # Copyright (C) 2005 Fernando Perez. <fperez@colorado.edu>
38 # Copyright (C) 2005 Fernando Perez. <fperez@colorado.edu>
@@ -46,7 +46,7 b" __author__ = '%s <%s>' % Release.authors['Fernando']"
46 __license__ = Release.license
46 __license__ = Release.license
47 __version__ = Release.version
47 __version__ = Release.version
48
48
49 import os
49 import os,bisect
50
50
51 # List here all the default hooks. For now it's just the editor functions
51 # List here all the default hooks. For now it's just the editor functions
52 # but over time we'll move here all the public API for user-accessible things.
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 os.system('vim --cmd "set errorformat=%f:%l:%c:%m" -q ' + t.name)
93 os.system('vim --cmd "set errorformat=%f:%l:%c:%m" -q ' + t.name)
94 finally:
94 finally:
95 t.close()
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 from IPython import Magic
92 from IPython import Magic
93
93 import new
94 setattr(Magic.Magic, "magic_" + magicname, func)
94 im = new.instancemethod(func,__IP, __IP.__class__)
95 setattr(__IP, "magic_" + magicname, im)
95
96
96 class asmagic:
97 class asmagic:
97 """ Decorator for exposing magics in a friendly 2.4 decorator form
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 self.name = name
126 self.name = name
127 self.prio = priority
126
128
127 def __call__(self,f):
129 def __call__(self,f):
128 set_hook(self.name, f)
130 set_hook(self.name, f, self.prio)
129 return f
131 return f
130
132
131
133
@@ -6,7 +6,7 b' Requires Python 2.3 or newer.'
6
6
7 This file contains all the classes and helper functions specific to IPython.
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 # Set all default hooks, defined in the IPython.hooks module.
401 # Set all default hooks, defined in the IPython.hooks module.
402 hooks = IPython.hooks
402 hooks = IPython.hooks
403 for hook_name in hooks.__all__:
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 # Flag to mark unconditional exit
407 # Flag to mark unconditional exit
407 self.exit_now = False
408 self.exit_now = False
@@ -707,17 +708,31 b' class InteractiveShell(object,Magic):'
707 __builtin__.__dict__[biname] = bival
708 __builtin__.__dict__[biname] = bival
708 self.builtins_added.clear()
709 self.builtins_added.clear()
709
710
710 def set_hook(self,name,hook):
711 def set_hook(self,name,hook, priority = 50):
711 """set_hook(name,hook) -> sets an internal IPython hook.
712 """set_hook(name,hook) -> sets an internal IPython hook.
712
713
713 IPython exposes some of its internal API as user-modifiable hooks. By
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 adding your function to one of these hooks, you can modify IPython's
715 call at runtime your own routines."""
716 behavior to call at runtime your own routines."""
716
717
717 # At some point in the future, this should validate the hook before it
718 # At some point in the future, this should validate the hook before it
718 # accepts it. Probably at least check that the hook takes the number
719 # accepts it. Probably at least check that the hook takes the number
719 # of args it's supposed to.
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 def set_custom_exc(self,exc_tuple,handler):
737 def set_custom_exc(self,exc_tuple,handler):
723 """set_custom_exc(exc_tuple,handler)
738 """set_custom_exc(exc_tuple,handler)
@@ -9,6 +9,12 b''
9 backslash (as yielded by tab completer) is still space;
9 backslash (as yielded by tab completer) is still space;
10 "%cd long\ name" works as expected.
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 2006-01-13 Ville Vainio <vivainio@gmail.com>
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