##// END OF EJS Templates
Walter's patch for ipapi.py & hooks.py: TryNext exception can now...
vivainio -
Show More
@@ -1,189 +1,191 b''
1 """hooks for IPython.
1 """hooks for IPython.
2
2
3 In Python, it is possible to overwrite any method of any object if you really
3 In Python, it is possible to overwrite any method of any object if you really
4 want to. But IPython exposes a few 'hooks', methods which are _designed_ to
4 want to. But IPython exposes a few 'hooks', methods which are _designed_ to
5 be overwritten by users for customization purposes. This module defines the
5 be overwritten by users for customization purposes. This module defines the
6 default versions of all such hooks, which get used by IPython if not
6 default versions of all such hooks, which get used by IPython if not
7 overridden by the user.
7 overridden by the user.
8
8
9 hooks are simple functions, but they should be declared with 'self' as their
9 hooks are simple functions, but they should be declared with 'self' as their
10 first argument, because when activated they are registered into IPython as
10 first argument, because when activated they are registered into IPython as
11 instance methods. The self argument will be the IPython running instance
11 instance methods. The self argument will be the IPython running instance
12 itself, so hooks have full access to the entire IPython object.
12 itself, so hooks have full access to the entire IPython object.
13
13
14 If you wish to define a new hook and activate it, you need to put the
14 If you wish to define a new hook and activate it, you need to put the
15 necessary code into a python file which can be either imported or execfile()'d
15 necessary code into a python file which can be either imported or execfile()'d
16 from within your ipythonrc configuration.
16 from within your ipythonrc configuration.
17
17
18 For example, suppose that you have a module called 'myiphooks' in your
18 For example, suppose that you have a module called 'myiphooks' in your
19 PYTHONPATH, which contains the following definition:
19 PYTHONPATH, which contains the following definition:
20
20
21 import os
21 import os
22 import IPython.ipapi
22 import IPython.ipapi
23 ip = IPython.ipapi.get()
23 ip = IPython.ipapi.get()
24
24
25 def calljed(self,filename, linenum):
25 def calljed(self,filename, linenum):
26 "My editor hook calls the jed editor directly."
26 "My editor hook calls the jed editor directly."
27 print "Calling my own editor, jed ..."
27 print "Calling my own editor, jed ..."
28 os.system('jed +%d %s' % (linenum,filename))
28 os.system('jed +%d %s' % (linenum,filename))
29
29
30 ip.set_hook('editor', calljed)
30 ip.set_hook('editor', calljed)
31
31
32 You can then enable the functionality by doing 'import myiphooks'
32 You can then enable the functionality by doing 'import myiphooks'
33 somewhere in your configuration files or ipython command line.
33 somewhere in your configuration files or ipython command line.
34
34
35 $Id: hooks.py 1214 2006-03-16 17:22:15Z vivainio $"""
35 $Id: hooks.py 1274 2006-04-26 14:01:37Z vivainio $"""
36
36
37 #*****************************************************************************
37 #*****************************************************************************
38 # Copyright (C) 2005 Fernando Perez. <fperez@colorado.edu>
38 # Copyright (C) 2005 Fernando Perez. <fperez@colorado.edu>
39 #
39 #
40 # Distributed under the terms of the BSD License. The full license is in
40 # Distributed under the terms of the BSD License. The full license is in
41 # the file COPYING, distributed as part of this software.
41 # the file COPYING, distributed as part of this software.
42 #*****************************************************************************
42 #*****************************************************************************
43
43
44 from IPython import Release
44 from IPython import Release
45 from IPython import ipapi
45 from IPython import ipapi
46 __author__ = '%s <%s>' % Release.authors['Fernando']
46 __author__ = '%s <%s>' % Release.authors['Fernando']
47 __license__ = Release.license
47 __license__ = Release.license
48 __version__ = Release.version
48 __version__ = Release.version
49
49
50 import os,bisect
50 import os,bisect
51 from genutils import Term
51 from genutils import Term
52 from pprint import pformat
52 from pprint import pformat
53
53
54 # List here all the default hooks. For now it's just the editor functions
54 # List here all the default hooks. For now it's just the editor functions
55 # but over time we'll move here all the public API for user-accessible things.
55 # but over time we'll move here all the public API for user-accessible things.
56 __all__ = ['editor', 'fix_error_editor', 'result_display',
56 __all__ = ['editor', 'fix_error_editor', 'result_display',
57 'input_prefilter', 'shutdown_hook', 'late_startup_hook']
57 'input_prefilter', 'shutdown_hook', 'late_startup_hook']
58
58
59 def editor(self,filename, linenum=None):
59 def editor(self,filename, linenum=None):
60 """Open the default editor at the given filename and linenumber.
60 """Open the default editor at the given filename and linenumber.
61
61
62 This is IPython's default editor hook, you can use it as an example to
62 This is IPython's default editor hook, you can use it as an example to
63 write your own modified one. To set your own editor function as the
63 write your own modified one. To set your own editor function as the
64 new editor hook, call ip.set_hook('editor',yourfunc)."""
64 new editor hook, call ip.set_hook('editor',yourfunc)."""
65
65
66 # IPython configures a default editor at startup by reading $EDITOR from
66 # IPython configures a default editor at startup by reading $EDITOR from
67 # the environment, and falling back on vi (unix) or notepad (win32).
67 # the environment, and falling back on vi (unix) or notepad (win32).
68 editor = self.rc.editor
68 editor = self.rc.editor
69
69
70 # marker for at which line to open the file (for existing objects)
70 # marker for at which line to open the file (for existing objects)
71 if linenum is None or editor=='notepad':
71 if linenum is None or editor=='notepad':
72 linemark = ''
72 linemark = ''
73 else:
73 else:
74 linemark = '+%d' % linenum
74 linemark = '+%d' % linenum
75
75
76 # Enclose in quotes if necessary and legal
76 # Enclose in quotes if necessary and legal
77 if ' ' in editor and os.path.isfile(editor) and editor[0] != '"':
77 if ' ' in editor and os.path.isfile(editor) and editor[0] != '"':
78 editor = '"%s"' % editor
78 editor = '"%s"' % editor
79
79
80 # Call the actual editor
80 # Call the actual editor
81 os.system('%s %s %s' % (editor,linemark,filename))
81 os.system('%s %s %s' % (editor,linemark,filename))
82
82
83 import tempfile
83 import tempfile
84 def fix_error_editor(self,filename,linenum,column,msg):
84 def fix_error_editor(self,filename,linenum,column,msg):
85 """Open the editor at the given filename, linenumber, column and
85 """Open the editor at the given filename, linenumber, column and
86 show an error message. This is used for correcting syntax errors.
86 show an error message. This is used for correcting syntax errors.
87 The current implementation only has special support for the VIM editor,
87 The current implementation only has special support for the VIM editor,
88 and falls back on the 'editor' hook if VIM is not used.
88 and falls back on the 'editor' hook if VIM is not used.
89
89
90 Call ip.set_hook('fix_error_editor',youfunc) to use your own function,
90 Call ip.set_hook('fix_error_editor',youfunc) to use your own function,
91 """
91 """
92 def vim_quickfix_file():
92 def vim_quickfix_file():
93 t = tempfile.NamedTemporaryFile()
93 t = tempfile.NamedTemporaryFile()
94 t.write('%s:%d:%d:%s\n' % (filename,linenum,column,msg))
94 t.write('%s:%d:%d:%s\n' % (filename,linenum,column,msg))
95 t.flush()
95 t.flush()
96 return t
96 return t
97 if os.path.basename(self.rc.editor) != 'vim':
97 if os.path.basename(self.rc.editor) != 'vim':
98 self.hooks.editor(filename,linenum)
98 self.hooks.editor(filename,linenum)
99 return
99 return
100 t = vim_quickfix_file()
100 t = vim_quickfix_file()
101 try:
101 try:
102 os.system('vim --cmd "set errorformat=%f:%l:%c:%m" -q ' + t.name)
102 os.system('vim --cmd "set errorformat=%f:%l:%c:%m" -q ' + t.name)
103 finally:
103 finally:
104 t.close()
104 t.close()
105
105
106
106
107 class CommandChainDispatcher:
107 class CommandChainDispatcher:
108 """ Dispatch calls to a chain of commands until some func can handle it
108 """ Dispatch calls to a chain of commands until some func can handle it
109
109
110 Usage: instantiate, execute "add" to add commands (with optional
110 Usage: instantiate, execute "add" to add commands (with optional
111 priority), execute normally via f() calling mechanism.
111 priority), execute normally via f() calling mechanism.
112
112
113 """
113 """
114 def __init__(self,commands=None):
114 def __init__(self,commands=None):
115 if commands is None:
115 if commands is None:
116 self.chain = []
116 self.chain = []
117 else:
117 else:
118 self.chain = commands
118 self.chain = commands
119
119
120
120
121 def __call__(self,*args, **kw):
121 def __call__(self,*args, **kw):
122 """ Command chain is called just like normal func.
122 """ Command chain is called just like normal func.
123
123
124 This will call all funcs in chain with the same args as were given to this
124 This will call all funcs in chain with the same args as were given to this
125 function, and return the result of first func that didn't raise
125 function, and return the result of first func that didn't raise
126 TryNext """
126 TryNext """
127
127
128 for prio,cmd in self.chain:
128 for prio,cmd in self.chain:
129 #print "prio",prio,"cmd",cmd #dbg
129 #print "prio",prio,"cmd",cmd #dbg
130 try:
130 try:
131 ret = cmd(*args, **kw)
131 ret = cmd(*args, **kw)
132 return ret
132 return ret
133 except ipapi.TryNext:
133 except ipapi.TryNext, exc:
134 pass
134 if exc.args or exc.kwargs:
135 args = exc.args
136 kw = exc.kwargs
135
137
136 def __str__(self):
138 def __str__(self):
137 return str(self.chain)
139 return str(self.chain)
138
140
139 def add(self, func, priority=0):
141 def add(self, func, priority=0):
140 """ Add a func to the cmd chain with given priority """
142 """ Add a func to the cmd chain with given priority """
141 bisect.insort(self.chain,(priority,func))
143 bisect.insort(self.chain,(priority,func))
142
144
143 def result_display(self,arg):
145 def result_display(self,arg):
144 """ Default display hook.
146 """ Default display hook.
145
147
146 Called for displaying the result to the user.
148 Called for displaying the result to the user.
147 """
149 """
148
150
149 if self.rc.pprint:
151 if self.rc.pprint:
150 out = pformat(arg)
152 out = pformat(arg)
151 if '\n' in out:
153 if '\n' in out:
152 # So that multi-line strings line up with the left column of
154 # So that multi-line strings line up with the left column of
153 # the screen, instead of having the output prompt mess up
155 # the screen, instead of having the output prompt mess up
154 # their first line.
156 # their first line.
155 Term.cout.write('\n')
157 Term.cout.write('\n')
156 print >>Term.cout, out
158 print >>Term.cout, out
157 else:
159 else:
158 print >>Term.cout, arg
160 print >>Term.cout, arg
159 # the default display hook doesn't manipulate the value to put in history
161 # the default display hook doesn't manipulate the value to put in history
160 return None
162 return None
161
163
162 def input_prefilter(self,line):
164 def input_prefilter(self,line):
163 """ Default input prefilter
165 """ Default input prefilter
164
166
165 This returns the line as unchanged, so that the interpreter
167 This returns the line as unchanged, so that the interpreter
166 knows that nothing was done and proceeds with "classic" prefiltering
168 knows that nothing was done and proceeds with "classic" prefiltering
167 (%magics, !shell commands etc.).
169 (%magics, !shell commands etc.).
168
170
169 Note that leading whitespace is not passed to this hook. Prefilter
171 Note that leading whitespace is not passed to this hook. Prefilter
170 can't alter indentation.
172 can't alter indentation.
171
173
172 """
174 """
173 #print "attempt to rewrite",line #dbg
175 #print "attempt to rewrite",line #dbg
174 return line
176 return line
175
177
176 def shutdown_hook(self):
178 def shutdown_hook(self):
177 """ default shutdown hook
179 """ default shutdown hook
178
180
179 Typically, shotdown hooks should raise TryNext so all shutdown ops are done
181 Typically, shotdown hooks should raise TryNext so all shutdown ops are done
180 """
182 """
181
183
182 #print "default shutdown hook ok" # dbg
184 #print "default shutdown hook ok" # dbg
183 return
185 return
184
186
185 def late_startup_hook(self):
187 def late_startup_hook(self):
186 """ Executed after ipython has been constructed and configured
188 """ Executed after ipython has been constructed and configured
187
189
188 """
190 """
189 #print "default startup hook ok" # dbg
191 #print "default startup hook ok" # dbg
@@ -1,197 +1,203 b''
1 ''' IPython customization API
1 ''' IPython customization API
2
2
3 Your one-stop module for configuring & extending ipython
3 Your one-stop module for configuring & extending ipython
4
4
5 The API will probably break when ipython 1.0 is released, but so
5 The API will probably break when ipython 1.0 is released, but so
6 will the other configuration method (rc files).
6 will the other configuration method (rc files).
7
7
8 All names prefixed by underscores are for internal use, not part
8 All names prefixed by underscores are for internal use, not part
9 of the public api.
9 of the public api.
10
10
11 Below is an example that you can just put to a module and import from ipython.
11 Below is an example that you can just put to a module and import from ipython.
12
12
13 A good practice is to install the config script below as e.g.
13 A good practice is to install the config script below as e.g.
14
14
15 ~/.ipython/my_private_conf.py
15 ~/.ipython/my_private_conf.py
16
16
17 And do
17 And do
18
18
19 import_mod my_private_conf
19 import_mod my_private_conf
20
20
21 in ~/.ipython/ipythonrc
21 in ~/.ipython/ipythonrc
22
22
23 That way the module is imported at startup and you can have all your
23 That way the module is imported at startup and you can have all your
24 personal configuration (as opposed to boilerplate ipythonrc-PROFILENAME
24 personal configuration (as opposed to boilerplate ipythonrc-PROFILENAME
25 stuff) in there.
25 stuff) in there.
26
26
27 -----------------------------------------------
27 -----------------------------------------------
28 import IPython.ipapi as ip
28 import IPython.ipapi as ip
29
29
30 def ankka_f(self, arg):
30 def ankka_f(self, arg):
31 print "Ankka",self,"says uppercase:",arg.upper()
31 print "Ankka",self,"says uppercase:",arg.upper()
32
32
33 ip.expose_magic("ankka",ankka_f)
33 ip.expose_magic("ankka",ankka_f)
34
34
35 ip.magic('alias sayhi echo "Testing, hi ok"')
35 ip.magic('alias sayhi echo "Testing, hi ok"')
36 ip.magic('alias helloworld echo "Hello world"')
36 ip.magic('alias helloworld echo "Hello world"')
37 ip.system('pwd')
37 ip.system('pwd')
38
38
39 ip.ex('import re')
39 ip.ex('import re')
40 ip.ex("""
40 ip.ex("""
41 def funcci(a,b):
41 def funcci(a,b):
42 print a+b
42 print a+b
43 print funcci(3,4)
43 print funcci(3,4)
44 """)
44 """)
45 ip.ex("funcci(348,9)")
45 ip.ex("funcci(348,9)")
46
46
47 def jed_editor(self,filename, linenum=None):
47 def jed_editor(self,filename, linenum=None):
48 print "Calling my own editor, jed ... via hook!"
48 print "Calling my own editor, jed ... via hook!"
49 import os
49 import os
50 if linenum is None: linenum = 0
50 if linenum is None: linenum = 0
51 os.system('jed +%d %s' % (linenum, filename))
51 os.system('jed +%d %s' % (linenum, filename))
52 print "exiting jed"
52 print "exiting jed"
53
53
54 ip.set_hook('editor',jed_editor)
54 ip.set_hook('editor',jed_editor)
55
55
56 o = ip.options()
56 o = ip.options()
57 o.autocall = 2 # FULL autocall mode
57 o.autocall = 2 # FULL autocall mode
58
58
59 print "done!"
59 print "done!"
60
60
61 '''
61 '''
62
62
63
63
64 class TryNext(Exception):
64 class TryNext(Exception):
65 """ Try next hook exception.
65 """ Try next hook exception.
66
66
67 Raise this in your hook function to indicate that the next
67 Raise this in your hook function to indicate that the next
68 hook handler should be used to handle the operation.
68 hook handler should be used to handle the operation.
69 If you pass arguments to the constructor those arguments will be
70 used by the next hook instead of the original ones.
69 """
71 """
70
72
71
73 def __init__(self, *args, **kwargs):
74 self.args = args
75 self.kwargs = kwargs
76
77
72 # contains the most recently instantiated IPApi
78 # contains the most recently instantiated IPApi
73 _recent = None
79 _recent = None
74
80
75 def get():
81 def get():
76 """ Get an IPApi object, or None if not running under ipython
82 """ Get an IPApi object, or None if not running under ipython
77
83
78 Running this should be the first thing you do when writing
84 Running this should be the first thing you do when writing
79 extensions that can be imported as normal modules. You can then
85 extensions that can be imported as normal modules. You can then
80 direct all the configuration operations against the returned
86 direct all the configuration operations against the returned
81 object.
87 object.
82
88
83 """
89 """
84
90
85 return _recent
91 return _recent
86
92
87
93
88
94
89 class IPApi:
95 class IPApi:
90 """ The actual API class for configuring IPython
96 """ The actual API class for configuring IPython
91
97
92 You should do all of the IPython configuration by getting
98 You should do all of the IPython configuration by getting
93 an IPApi object with IPython.ipapi.get() and using the provided
99 an IPApi object with IPython.ipapi.get() and using the provided
94 methods.
100 methods.
95
101
96 """
102 """
97 def __init__(self,ip):
103 def __init__(self,ip):
98
104
99 self.magic = ip.ipmagic
105 self.magic = ip.ipmagic
100
106
101 self.system = ip.ipsystem
107 self.system = ip.ipsystem
102
108
103 self.set_hook = ip.set_hook
109 self.set_hook = ip.set_hook
104
110
105 self.set_custom_exc = ip.set_custom_exc
111 self.set_custom_exc = ip.set_custom_exc
106
112
107 self.IP = ip
113 self.IP = ip
108 global _recent
114 global _recent
109 _recent = self
115 _recent = self
110
116
111
117
112
118
113 def options(self):
119 def options(self):
114 """ All configurable variables """
120 """ All configurable variables """
115 return self.IP.rc
121 return self.IP.rc
116
122
117 def user_ns(self):
123 def user_ns(self):
118 return self.IP.user_ns
124 return self.IP.user_ns
119
125
120 def expose_magic(self,magicname, func):
126 def expose_magic(self,magicname, func):
121 ''' Expose own function as magic function for ipython
127 ''' Expose own function as magic function for ipython
122
128
123 def foo_impl(self,parameter_s=''):
129 def foo_impl(self,parameter_s=''):
124 """My very own magic!. (Use docstrings, IPython reads them)."""
130 """My very own magic!. (Use docstrings, IPython reads them)."""
125 print 'Magic function. Passed parameter is between < >: <'+parameter_s+'>'
131 print 'Magic function. Passed parameter is between < >: <'+parameter_s+'>'
126 print 'The self object is:',self
132 print 'The self object is:',self
127
133
128 ipapi.expose_magic("foo",foo_impl)
134 ipapi.expose_magic("foo",foo_impl)
129 '''
135 '''
130
136
131 import new
137 import new
132 im = new.instancemethod(func,self.IP, self.IP.__class__)
138 im = new.instancemethod(func,self.IP, self.IP.__class__)
133 setattr(self.IP, "magic_" + magicname, im)
139 setattr(self.IP, "magic_" + magicname, im)
134
140
135
141
136 def ex(self,cmd):
142 def ex(self,cmd):
137 """ Execute a normal python statement in user namespace """
143 """ Execute a normal python statement in user namespace """
138 exec cmd in self.user_ns()
144 exec cmd in self.user_ns()
139
145
140 def ev(self,expr):
146 def ev(self,expr):
141 """ Evaluate python expression expr in user namespace
147 """ Evaluate python expression expr in user namespace
142
148
143 Returns the result of evaluation"""
149 Returns the result of evaluation"""
144 return eval(expr,self.user_ns())
150 return eval(expr,self.user_ns())
145
151
146 def meta(self):
152 def meta(self):
147 """ Get a session-specific data store
153 """ Get a session-specific data store
148
154
149 Object returned by this method can be used to store
155 Object returned by this method can be used to store
150 data that should persist through the ipython session.
156 data that should persist through the ipython session.
151 """
157 """
152 return self.IP.meta
158 return self.IP.meta
153
159
154 def getdb(self):
160 def getdb(self):
155 """ Return a handle to persistent dict-like database
161 """ Return a handle to persistent dict-like database
156
162
157 Return a PickleShareDB object.
163 Return a PickleShareDB object.
158 """
164 """
159 return self.IP.db
165 return self.IP.db
160 def runlines(self,lines):
166 def runlines(self,lines):
161 """ Run the specified lines in interpreter, honoring ipython directives.
167 """ Run the specified lines in interpreter, honoring ipython directives.
162
168
163 This allows %magic and !shell escape notations.
169 This allows %magic and !shell escape notations.
164
170
165 Takes either all lines in one string or list of lines.
171 Takes either all lines in one string or list of lines.
166 """
172 """
167 if isinstance(lines,basestring):
173 if isinstance(lines,basestring):
168 self.IP.runlines(lines)
174 self.IP.runlines(lines)
169 else:
175 else:
170 self.IP.runlines('\n'.join(lines))
176 self.IP.runlines('\n'.join(lines))
171
177
172
178
173 def launch_new_instance(user_ns = None):
179 def launch_new_instance(user_ns = None):
174 """ Create and start a new ipython instance.
180 """ Create and start a new ipython instance.
175
181
176 This can be called even without having an already initialized
182 This can be called even without having an already initialized
177 ipython session running.
183 ipython session running.
178
184
179 This is also used as the egg entry point for the 'ipython' script.
185 This is also used as the egg entry point for the 'ipython' script.
180
186
181 """
187 """
182 ses = create_session(user_ns)
188 ses = create_session(user_ns)
183 ses.mainloop()
189 ses.mainloop()
184
190
185
191
186 def create_session(user_ns = None):
192 def create_session(user_ns = None):
187 """ Creates, but does not launch an IPython session.
193 """ Creates, but does not launch an IPython session.
188
194
189 Later on you can call obj.mainloop() on the returned object.
195 Later on you can call obj.mainloop() on the returned object.
190
196
191 This should *not* be run when a session exists already.
197 This should *not* be run when a session exists already.
192
198
193 """
199 """
194 if user_ns is not None:
200 if user_ns is not None:
195 user_ns["__name__"] = user_ns.get("__name__",'ipy_session')
201 user_ns["__name__"] = user_ns.get("__name__",'ipy_session')
196 import IPython
202 import IPython
197 return IPython.Shell.start(user_ns = user_ns) No newline at end of file
203 return IPython.Shell.start(user_ns = user_ns)
General Comments 0
You need to be logged in to leave comments. Login now