##// END OF EJS Templates
Remove args/kwargs handling in TryNext....
Bradley M. Froehle -
Show More
@@ -1,66 +1,53 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Global exception classes for IPython.core.
3 Global exception classes for IPython.core.
4
4
5 Authors:
5 Authors:
6
6
7 * Brian Granger
7 * Brian Granger
8 * Fernando Perez
8 * Fernando Perez
9 * Min Ragan-Kelley
9 * Min Ragan-Kelley
10
10
11 Notes
11 Notes
12 -----
12 -----
13 """
13 """
14
14
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Copyright (C) 2008-2011 The IPython Development Team
16 # Copyright (C) 2008-2011 The IPython Development Team
17 #
17 #
18 # Distributed under the terms of the BSD License. The full license is in
18 # Distributed under the terms of the BSD License. The full license is in
19 # the file COPYING, distributed as part of this software.
19 # the file COPYING, distributed as part of this software.
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21
21
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23 # Imports
23 # Imports
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25
25
26 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
27 # Exception classes
27 # Exception classes
28 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
29
29
30 class IPythonCoreError(Exception):
30 class IPythonCoreError(Exception):
31 pass
31 pass
32
32
33
33
34 class TryNext(IPythonCoreError):
34 class TryNext(IPythonCoreError):
35 """Try next hook exception.
35 """Try next hook exception.
36
36
37 Raise this in your hook function to indicate that the next hook handler
37 Raise this in your hook function to indicate that the next hook handler
38 should be used to handle the operation. If you pass arguments to the
38 should be used to handle the operation.
39 constructor those arguments will be used by the next hook instead of the
40 original ones.
41
42 A _msg argument will not be passed on, so it can be used as a displayable
43 error message.
44 """
39 """
45
40
46 def __init__(self, _msg="", *args, **kwargs):
47 self.args = args
48 self.kwargs = kwargs
49 self.msg = _msg
50
51 def __str__(self):
52 return str(self.msg)
53
54 class UsageError(IPythonCoreError):
41 class UsageError(IPythonCoreError):
55 """Error in magic function arguments, etc.
42 """Error in magic function arguments, etc.
56
43
57 Something that probably won't warrant a full traceback, but should
44 Something that probably won't warrant a full traceback, but should
58 nevertheless interrupt a macro / batch file.
45 nevertheless interrupt a macro / batch file.
59 """
46 """
60
47
61 class StdinNotImplementedError(IPythonCoreError, NotImplementedError):
48 class StdinNotImplementedError(IPythonCoreError, NotImplementedError):
62 """raw_input was requested in a context where it is not supported
49 """raw_input was requested in a context where it is not supported
63
50
64 For use in IPython kernels, where only some frontends may support
51 For use in IPython kernels, where only some frontends may support
65 stdin requests.
52 stdin requests.
66 """
53 """
@@ -1,231 +1,229 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 profile's ipython_config.py configuration.
16 from within your profile's ipython_config.py 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 from IPython.core import ipapi
22 from IPython.core import ipapi
23 ip = ipapi.get()
23 ip = 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 if os.system('jed +%d %s' % (linenum,filename)) != 0:
28 if os.system('jed +%d %s' % (linenum,filename)) != 0:
29 raise TryNext()
29 raise TryNext()
30
30
31 ip.set_hook('editor', calljed)
31 ip.set_hook('editor', calljed)
32
32
33 You can then enable the functionality by doing 'import myiphooks'
33 You can then enable the functionality by doing 'import myiphooks'
34 somewhere in your configuration files or ipython command line.
34 somewhere in your configuration files or ipython command line.
35 """
35 """
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 import os, bisect
44 import os, bisect
45 import subprocess
45 import subprocess
46 import sys
46 import sys
47
47
48 from IPython.core.error import TryNext
48 from IPython.core.error import TryNext
49
49
50 # List here all the default hooks. For now it's just the editor functions
50 # List here all the default hooks. For now it's just the editor functions
51 # but over time we'll move here all the public API for user-accessible things.
51 # but over time we'll move here all the public API for user-accessible things.
52
52
53 __all__ = ['editor', 'fix_error_editor', 'synchronize_with_editor',
53 __all__ = ['editor', 'fix_error_editor', 'synchronize_with_editor',
54 'input_prefilter', 'shutdown_hook', 'late_startup_hook',
54 'input_prefilter', 'shutdown_hook', 'late_startup_hook',
55 'show_in_pager','pre_prompt_hook',
55 'show_in_pager','pre_prompt_hook',
56 'pre_run_code_hook', 'clipboard_get']
56 'pre_run_code_hook', 'clipboard_get']
57
57
58 def editor(self, filename, linenum=None, wait=True):
58 def editor(self, filename, linenum=None, wait=True):
59 """Open the default editor at the given filename and linenumber.
59 """Open the default editor at the given filename and linenumber.
60
60
61 This is IPython's default editor hook, you can use it as an example to
61 This is IPython's default editor hook, you can use it as an example to
62 write your own modified one. To set your own editor function as the
62 write your own modified one. To set your own editor function as the
63 new editor hook, call ip.set_hook('editor',yourfunc)."""
63 new editor hook, call ip.set_hook('editor',yourfunc)."""
64
64
65 # IPython configures a default editor at startup by reading $EDITOR from
65 # IPython configures a default editor at startup by reading $EDITOR from
66 # the environment, and falling back on vi (unix) or notepad (win32).
66 # the environment, and falling back on vi (unix) or notepad (win32).
67 editor = self.editor
67 editor = self.editor
68
68
69 # marker for at which line to open the file (for existing objects)
69 # marker for at which line to open the file (for existing objects)
70 if linenum is None or editor=='notepad':
70 if linenum is None or editor=='notepad':
71 linemark = ''
71 linemark = ''
72 else:
72 else:
73 linemark = '+%d' % int(linenum)
73 linemark = '+%d' % int(linenum)
74
74
75 # Enclose in quotes if necessary and legal
75 # Enclose in quotes if necessary and legal
76 if ' ' in editor and os.path.isfile(editor) and editor[0] != '"':
76 if ' ' in editor and os.path.isfile(editor) and editor[0] != '"':
77 editor = '"%s"' % editor
77 editor = '"%s"' % editor
78
78
79 # Call the actual editor
79 # Call the actual editor
80 proc = subprocess.Popen('%s %s %s' % (editor, linemark, filename),
80 proc = subprocess.Popen('%s %s %s' % (editor, linemark, filename),
81 shell=True)
81 shell=True)
82 if wait and proc.wait() != 0:
82 if wait and proc.wait() != 0:
83 raise TryNext()
83 raise TryNext()
84
84
85 import tempfile
85 import tempfile
86 def fix_error_editor(self,filename,linenum,column,msg):
86 def fix_error_editor(self,filename,linenum,column,msg):
87 """Open the editor at the given filename, linenumber, column and
87 """Open the editor at the given filename, linenumber, column and
88 show an error message. This is used for correcting syntax errors.
88 show an error message. This is used for correcting syntax errors.
89 The current implementation only has special support for the VIM editor,
89 The current implementation only has special support for the VIM editor,
90 and falls back on the 'editor' hook if VIM is not used.
90 and falls back on the 'editor' hook if VIM is not used.
91
91
92 Call ip.set_hook('fix_error_editor',youfunc) to use your own function,
92 Call ip.set_hook('fix_error_editor',youfunc) to use your own function,
93 """
93 """
94 def vim_quickfix_file():
94 def vim_quickfix_file():
95 t = tempfile.NamedTemporaryFile()
95 t = tempfile.NamedTemporaryFile()
96 t.write('%s:%d:%d:%s\n' % (filename,linenum,column,msg))
96 t.write('%s:%d:%d:%s\n' % (filename,linenum,column,msg))
97 t.flush()
97 t.flush()
98 return t
98 return t
99 if os.path.basename(self.editor) != 'vim':
99 if os.path.basename(self.editor) != 'vim':
100 self.hooks.editor(filename,linenum)
100 self.hooks.editor(filename,linenum)
101 return
101 return
102 t = vim_quickfix_file()
102 t = vim_quickfix_file()
103 try:
103 try:
104 if os.system('vim --cmd "set errorformat=%f:%l:%c:%m" -q ' + t.name):
104 if os.system('vim --cmd "set errorformat=%f:%l:%c:%m" -q ' + t.name):
105 raise TryNext()
105 raise TryNext()
106 finally:
106 finally:
107 t.close()
107 t.close()
108
108
109
109
110 def synchronize_with_editor(self, filename, linenum, column):
110 def synchronize_with_editor(self, filename, linenum, column):
111 pass
111 pass
112
112
113
113
114 class CommandChainDispatcher:
114 class CommandChainDispatcher:
115 """ Dispatch calls to a chain of commands until some func can handle it
115 """ Dispatch calls to a chain of commands until some func can handle it
116
116
117 Usage: instantiate, execute "add" to add commands (with optional
117 Usage: instantiate, execute "add" to add commands (with optional
118 priority), execute normally via f() calling mechanism.
118 priority), execute normally via f() calling mechanism.
119
119
120 """
120 """
121 def __init__(self,commands=None):
121 def __init__(self,commands=None):
122 if commands is None:
122 if commands is None:
123 self.chain = []
123 self.chain = []
124 else:
124 else:
125 self.chain = commands
125 self.chain = commands
126
126
127
127
128 def __call__(self,*args, **kw):
128 def __call__(self,*args, **kw):
129 """ Command chain is called just like normal func.
129 """ Command chain is called just like normal func.
130
130
131 This will call all funcs in chain with the same args as were given to
131 This will call all funcs in chain with the same args as were given to
132 this function, and return the result of first func that didn't raise
132 this function, and return the result of first func that didn't raise
133 TryNext"""
133 TryNext"""
134
134 last_exc = TryNext()
135 for prio,cmd in self.chain:
135 for prio,cmd in self.chain:
136 #print "prio",prio,"cmd",cmd #dbg
136 #print "prio",prio,"cmd",cmd #dbg
137 try:
137 try:
138 return cmd(*args, **kw)
138 return cmd(*args, **kw)
139 except TryNext, exc:
139 except TryNext as exc:
140 if exc.args or exc.kwargs:
140 last_exc = exc
141 args = exc.args
142 kw = exc.kwargs
143 # if no function will accept it, raise TryNext up to the caller
141 # if no function will accept it, raise TryNext up to the caller
144 raise TryNext(*args, **kw)
142 raise last_exc
145
143
146 def __str__(self):
144 def __str__(self):
147 return str(self.chain)
145 return str(self.chain)
148
146
149 def add(self, func, priority=0):
147 def add(self, func, priority=0):
150 """ Add a func to the cmd chain with given priority """
148 """ Add a func to the cmd chain with given priority """
151 bisect.insort(self.chain,(priority,func))
149 bisect.insort(self.chain,(priority,func))
152
150
153 def __iter__(self):
151 def __iter__(self):
154 """ Return all objects in chain.
152 """ Return all objects in chain.
155
153
156 Handy if the objects are not callable.
154 Handy if the objects are not callable.
157 """
155 """
158 return iter(self.chain)
156 return iter(self.chain)
159
157
160
158
161 def input_prefilter(self,line):
159 def input_prefilter(self,line):
162 """ Default input prefilter
160 """ Default input prefilter
163
161
164 This returns the line as unchanged, so that the interpreter
162 This returns the line as unchanged, so that the interpreter
165 knows that nothing was done and proceeds with "classic" prefiltering
163 knows that nothing was done and proceeds with "classic" prefiltering
166 (%magics, !shell commands etc.).
164 (%magics, !shell commands etc.).
167
165
168 Note that leading whitespace is not passed to this hook. Prefilter
166 Note that leading whitespace is not passed to this hook. Prefilter
169 can't alter indentation.
167 can't alter indentation.
170
168
171 """
169 """
172 #print "attempt to rewrite",line #dbg
170 #print "attempt to rewrite",line #dbg
173 return line
171 return line
174
172
175
173
176 def shutdown_hook(self):
174 def shutdown_hook(self):
177 """ default shutdown hook
175 """ default shutdown hook
178
176
179 Typically, shotdown hooks should raise TryNext so all shutdown ops are done
177 Typically, shotdown hooks should raise TryNext so all shutdown ops are done
180 """
178 """
181
179
182 #print "default shutdown hook ok" # dbg
180 #print "default shutdown hook ok" # dbg
183 return
181 return
184
182
185
183
186 def late_startup_hook(self):
184 def late_startup_hook(self):
187 """ Executed after ipython has been constructed and configured
185 """ Executed after ipython has been constructed and configured
188
186
189 """
187 """
190 #print "default startup hook ok" # dbg
188 #print "default startup hook ok" # dbg
191
189
192
190
193 def show_in_pager(self,s):
191 def show_in_pager(self,s):
194 """ Run a string through pager """
192 """ Run a string through pager """
195 # raising TryNext here will use the default paging functionality
193 # raising TryNext here will use the default paging functionality
196 raise TryNext
194 raise TryNext
197
195
198
196
199 def pre_prompt_hook(self):
197 def pre_prompt_hook(self):
200 """ Run before displaying the next prompt
198 """ Run before displaying the next prompt
201
199
202 Use this e.g. to display output from asynchronous operations (in order
200 Use this e.g. to display output from asynchronous operations (in order
203 to not mess up text entry)
201 to not mess up text entry)
204 """
202 """
205
203
206 return None
204 return None
207
205
208
206
209 def pre_run_code_hook(self):
207 def pre_run_code_hook(self):
210 """ Executed before running the (prefiltered) code in IPython """
208 """ Executed before running the (prefiltered) code in IPython """
211 return None
209 return None
212
210
213
211
214 def clipboard_get(self):
212 def clipboard_get(self):
215 """ Get text from the clipboard.
213 """ Get text from the clipboard.
216 """
214 """
217 from IPython.lib.clipboard import (
215 from IPython.lib.clipboard import (
218 osx_clipboard_get, tkinter_clipboard_get,
216 osx_clipboard_get, tkinter_clipboard_get,
219 win32_clipboard_get
217 win32_clipboard_get
220 )
218 )
221 if sys.platform == 'win32':
219 if sys.platform == 'win32':
222 chain = [win32_clipboard_get, tkinter_clipboard_get]
220 chain = [win32_clipboard_get, tkinter_clipboard_get]
223 elif sys.platform == 'darwin':
221 elif sys.platform == 'darwin':
224 chain = [osx_clipboard_get, tkinter_clipboard_get]
222 chain = [osx_clipboard_get, tkinter_clipboard_get]
225 else:
223 else:
226 chain = [tkinter_clipboard_get]
224 chain = [tkinter_clipboard_get]
227 dispatcher = CommandChainDispatcher()
225 dispatcher = CommandChainDispatcher()
228 for func in chain:
226 for func in chain:
229 dispatcher.add(func)
227 dispatcher.add(func)
230 text = dispatcher()
228 text = dispatcher()
231 return text
229 return text
@@ -1,56 +1,54 b''
1 """ Utilities for accessing the platform's clipboard.
1 """ Utilities for accessing the platform's clipboard.
2 """
2 """
3
3
4 import subprocess
4 import subprocess
5 import sys
5 import sys
6
6
7 from IPython.core.error import TryNext
7 from IPython.core.error import TryNext
8
8
9
9
10 def win32_clipboard_get():
10 def win32_clipboard_get():
11 """ Get the current clipboard's text on Windows.
11 """ Get the current clipboard's text on Windows.
12
12
13 Requires Mark Hammond's pywin32 extensions.
13 Requires Mark Hammond's pywin32 extensions.
14 """
14 """
15 try:
15 try:
16 import win32clipboard
16 import win32clipboard
17 except ImportError:
17 except ImportError:
18 message = ("Getting text from the clipboard requires the pywin32 "
18 raise TryNext("Getting text from the clipboard requires the pywin32 "
19 "extensions: http://sourceforge.net/projects/pywin32/")
19 "extensions: http://sourceforge.net/projects/pywin32/")
20 raise TryNext(_msg=message)
21 win32clipboard.OpenClipboard()
20 win32clipboard.OpenClipboard()
22 text = win32clipboard.GetClipboardData(win32clipboard.CF_TEXT)
21 text = win32clipboard.GetClipboardData(win32clipboard.CF_TEXT)
23 # FIXME: convert \r\n to \n?
22 # FIXME: convert \r\n to \n?
24 win32clipboard.CloseClipboard()
23 win32clipboard.CloseClipboard()
25 return text
24 return text
26
25
27 def osx_clipboard_get():
26 def osx_clipboard_get():
28 """ Get the clipboard's text on OS X.
27 """ Get the clipboard's text on OS X.
29 """
28 """
30 p = subprocess.Popen(['pbpaste', '-Prefer', 'ascii'],
29 p = subprocess.Popen(['pbpaste', '-Prefer', 'ascii'],
31 stdout=subprocess.PIPE)
30 stdout=subprocess.PIPE)
32 text, stderr = p.communicate()
31 text, stderr = p.communicate()
33 # Text comes in with old Mac \r line endings. Change them to \n.
32 # Text comes in with old Mac \r line endings. Change them to \n.
34 text = text.replace('\r', '\n')
33 text = text.replace('\r', '\n')
35 return text
34 return text
36
35
37 def tkinter_clipboard_get():
36 def tkinter_clipboard_get():
38 """ Get the clipboard's text using Tkinter.
37 """ Get the clipboard's text using Tkinter.
39
38
40 This is the default on systems that are not Windows or OS X. It may
39 This is the default on systems that are not Windows or OS X. It may
41 interfere with other UI toolkits and should be replaced with an
40 interfere with other UI toolkits and should be replaced with an
42 implementation that uses that toolkit.
41 implementation that uses that toolkit.
43 """
42 """
44 try:
43 try:
45 import Tkinter
44 import Tkinter
46 except ImportError:
45 except ImportError:
47 message = ("Getting text from the clipboard on this platform "
46 raise TryNext("Getting text from the clipboard on this platform "
48 "requires Tkinter.")
47 "requires Tkinter.")
49 raise TryNext(_msg=message)
50 root = Tkinter.Tk()
48 root = Tkinter.Tk()
51 root.withdraw()
49 root.withdraw()
52 text = root.clipboard_get()
50 text = root.clipboard_get()
53 root.destroy()
51 root.destroy()
54 return text
52 return text
55
53
56
54
@@ -1,27 +1,35 b''
1 =====================
1 =====================
2 Development version
2 Development version
3 =====================
3 =====================
4
4
5 This document describes in-flight development work.
5 This document describes in-flight development work.
6
6
7 Redesigned IPython notebook user interface
7 Redesigned IPython notebook user interface
8 ------------------------------------------
8 ------------------------------------------
9
9
10 .. add details
10 .. add details
11
11
12 Other new features
12 Other new features
13 ------------------
13 ------------------
14
14
15 * **%install_ext**: A new magic function to install an IPython extension from
15 * **%install_ext**: A new magic function to install an IPython extension from
16 a URL. E.g. ``%install_ext https://bitbucket.org/birkenfeld/ipython-physics/raw/d1310a2ab15d/physics.py``.
16 a URL. E.g. ``%install_ext https://bitbucket.org/birkenfeld/ipython-physics/raw/d1310a2ab15d/physics.py``.
17
17
18 * The :envvar:`IPYTHON_DIR` environment variable, introduced in the Great
18 * The :envvar:`IPYTHON_DIR` environment variable, introduced in the Great
19 Reorganization of 0.11 and existing only in versions 0.11-0.13, has been
19 Reorganization of 0.11 and existing only in versions 0.11-0.13, has been
20 deprecated. As described in :ghissue:`1167`, the complexity and confusion of
20 deprecated. As described in :ghissue:`1167`, the complexity and confusion of
21 migrating to this variable is not worth the aesthetic improvement. Please use
21 migrating to this variable is not worth the aesthetic improvement. Please use
22 the historical :envvar:`IPYTHONDIR` environment variable instead.
22 the historical :envvar:`IPYTHONDIR` environment variable instead.
23
23
24 * The default value of *interactivity* passed from
24 * The default value of *interactivity* passed from
25 :meth:`~IPython.core.interactiveshell.InteractiveShell.run_cell` to
25 :meth:`~IPython.core.interactiveshell.InteractiveShell.run_cell` to
26 :meth:`~IPython.core.interactiveshell.InteractiveShell.run_ast_nodes`
26 :meth:`~IPython.core.interactiveshell.InteractiveShell.run_ast_nodes`
27 is now configurable.
27 is now configurable.
28
29 Backwards incompatible changes
30 ------------------------------
31
32 * The exception :exc:`IPython.core.error.TryNext` previously accepted
33 arguments and keyword arguments to be passed to the next implementation
34 of the hook. This feature was removed as it made error message propagation
35 difficult and violated the principle of loose coupling.
General Comments 0
You need to be logged in to leave comments. Login now