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