##// END OF EJS Templates
Fix for 'man' formatting (mostly on OSX, but the fix is OK on linux)
Fernando Perez -
Show More
@@ -1,545 +1,546 b''
1 """A ZMQ-based subclass of InteractiveShell.
1 """A ZMQ-based subclass of InteractiveShell.
2
2
3 This code is meant to ease the refactoring of the base InteractiveShell into
3 This code is meant to ease the refactoring of the base InteractiveShell into
4 something with a cleaner architecture for 2-process use, without actually
4 something with a cleaner architecture for 2-process use, without actually
5 breaking InteractiveShell itself. So we're doing something a bit ugly, where
5 breaking InteractiveShell itself. So we're doing something a bit ugly, where
6 we subclass and override what we want to fix. Once this is working well, we
6 we subclass and override what we want to fix. Once this is working well, we
7 can go back to the base class and refactor the code for a cleaner inheritance
7 can go back to the base class and refactor the code for a cleaner inheritance
8 implementation that doesn't rely on so much monkeypatching.
8 implementation that doesn't rely on so much monkeypatching.
9
9
10 But this lets us maintain a fully working IPython as we develop the new
10 But this lets us maintain a fully working IPython as we develop the new
11 machinery. This should thus be thought of as scaffolding.
11 machinery. This should thus be thought of as scaffolding.
12 """
12 """
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 from __future__ import print_function
16 from __future__ import print_function
17
17
18 # Stdlib
18 # Stdlib
19 import inspect
19 import inspect
20 import os
20 import os
21 import re
21 import re
22
22
23 # Our own
23 # Our own
24 from IPython.core.interactiveshell import (
24 from IPython.core.interactiveshell import (
25 InteractiveShell, InteractiveShellABC
25 InteractiveShell, InteractiveShellABC
26 )
26 )
27 from IPython.core import page
27 from IPython.core import page
28 from IPython.core.displayhook import DisplayHook
28 from IPython.core.displayhook import DisplayHook
29 from IPython.core.macro import Macro
29 from IPython.core.macro import Macro
30 from IPython.core.payloadpage import install_payload_page
30 from IPython.core.payloadpage import install_payload_page
31 from IPython.utils import io
31 from IPython.utils import io
32 from IPython.utils.path import get_py_filename
32 from IPython.utils.path import get_py_filename
33 from IPython.utils.text import StringTypes
33 from IPython.utils.text import StringTypes
34 from IPython.utils.traitlets import Instance, Type, Dict
34 from IPython.utils.traitlets import Instance, Type, Dict
35 from IPython.utils.warn import warn
35 from IPython.utils.warn import warn
36 from IPython.zmq.session import extract_header
36 from IPython.zmq.session import extract_header
37 from session import Session
37 from session import Session
38
38
39 #-----------------------------------------------------------------------------
39 #-----------------------------------------------------------------------------
40 # Globals and side-effects
40 # Globals and side-effects
41 #-----------------------------------------------------------------------------
41 #-----------------------------------------------------------------------------
42
42
43 # Install the payload version of page.
43 # Install the payload version of page.
44 install_payload_page()
44 install_payload_page()
45
45
46 #-----------------------------------------------------------------------------
46 #-----------------------------------------------------------------------------
47 # Functions and classes
47 # Functions and classes
48 #-----------------------------------------------------------------------------
48 #-----------------------------------------------------------------------------
49
49
50 class ZMQDisplayHook(DisplayHook):
50 class ZMQDisplayHook(DisplayHook):
51
51
52 session = Instance(Session)
52 session = Instance(Session)
53 pub_socket = Instance('zmq.Socket')
53 pub_socket = Instance('zmq.Socket')
54 parent_header = Dict({})
54 parent_header = Dict({})
55
55
56 def set_parent(self, parent):
56 def set_parent(self, parent):
57 """Set the parent for outbound messages."""
57 """Set the parent for outbound messages."""
58 self.parent_header = extract_header(parent)
58 self.parent_header = extract_header(parent)
59
59
60 def start_displayhook(self):
60 def start_displayhook(self):
61 self.msg = self.session.msg(u'pyout', {}, parent=self.parent_header)
61 self.msg = self.session.msg(u'pyout', {}, parent=self.parent_header)
62
62
63 def write_output_prompt(self):
63 def write_output_prompt(self):
64 """Write the output prompt."""
64 """Write the output prompt."""
65 if self.do_full_cache:
65 if self.do_full_cache:
66 self.msg['content']['execution_count'] = self.prompt_count
66 self.msg['content']['execution_count'] = self.prompt_count
67
67
68 def write_result_repr(self, result_repr):
68 def write_result_repr(self, result_repr):
69 self.msg['content']['data'] = result_repr
69 self.msg['content']['data'] = result_repr
70
70
71 def finish_displayhook(self):
71 def finish_displayhook(self):
72 """Finish up all displayhook activities."""
72 """Finish up all displayhook activities."""
73 self.pub_socket.send_json(self.msg)
73 self.pub_socket.send_json(self.msg)
74 self.msg = None
74 self.msg = None
75
75
76
76
77 class ZMQInteractiveShell(InteractiveShell):
77 class ZMQInteractiveShell(InteractiveShell):
78 """A subclass of InteractiveShell for ZMQ."""
78 """A subclass of InteractiveShell for ZMQ."""
79
79
80 displayhook_class = Type(ZMQDisplayHook)
80 displayhook_class = Type(ZMQDisplayHook)
81
81
82 def init_environment(self):
82 def init_environment(self):
83 """Configure the user's environment.
83 """Configure the user's environment.
84
84
85 """
85 """
86 env = os.environ
86 env = os.environ
87 # These two ensure 'ls' produces nice coloring on BSD-derived systems
87 # These two ensure 'ls' produces nice coloring on BSD-derived systems
88 env['TERM'] = 'xterm-color'
88 env['TERM'] = 'xterm-color'
89 env['CLICOLOR'] = '1'
89 env['CLICOLOR'] = '1'
90 # Since normal pagers don't work at all (over pexpect we don't have
90 # Since normal pagers don't work at all (over pexpect we don't have
91 # single-key control of the subprocess), try to disable paging in
91 # single-key control of the subprocess), try to disable paging in
92 # subprocesses as much as possible.
92 # subprocesses as much as possible.
93 env['PAGER'] = 'cat'
93 env['PAGER'] = 'cat'
94 env['GIT_PAGER'] = 'cat'
94 env['GIT_PAGER'] = 'cat'
95
95
96 def auto_rewrite_input(self, cmd):
96 def auto_rewrite_input(self, cmd):
97 """Called to show the auto-rewritten input for autocall and friends.
97 """Called to show the auto-rewritten input for autocall and friends.
98
98
99 FIXME: this payload is currently not correctly processed by the
99 FIXME: this payload is currently not correctly processed by the
100 frontend.
100 frontend.
101 """
101 """
102 new = self.displayhook.prompt1.auto_rewrite() + cmd
102 new = self.displayhook.prompt1.auto_rewrite() + cmd
103 payload = dict(
103 payload = dict(
104 source='IPython.zmq.zmqshell.ZMQInteractiveShell.auto_rewrite_input',
104 source='IPython.zmq.zmqshell.ZMQInteractiveShell.auto_rewrite_input',
105 transformed_input=new,
105 transformed_input=new,
106 )
106 )
107 self.payload_manager.write_payload(payload)
107 self.payload_manager.write_payload(payload)
108
108
109 def ask_exit(self):
109 def ask_exit(self):
110 """Engage the exit actions."""
110 """Engage the exit actions."""
111 payload = dict(
111 payload = dict(
112 source='IPython.zmq.zmqshell.ZMQInteractiveShell.ask_exit',
112 source='IPython.zmq.zmqshell.ZMQInteractiveShell.ask_exit',
113 exit=True,
113 exit=True,
114 )
114 )
115 self.payload_manager.write_payload(payload)
115 self.payload_manager.write_payload(payload)
116
116
117 def _showtraceback(self, etype, evalue, stb):
117 def _showtraceback(self, etype, evalue, stb):
118
118
119 exc_content = {
119 exc_content = {
120 u'traceback' : stb,
120 u'traceback' : stb,
121 u'ename' : unicode(etype.__name__),
121 u'ename' : unicode(etype.__name__),
122 u'evalue' : unicode(evalue)
122 u'evalue' : unicode(evalue)
123 }
123 }
124
124
125 dh = self.displayhook
125 dh = self.displayhook
126 exc_msg = dh.session.msg(u'pyerr', exc_content, dh.parent_header)
126 exc_msg = dh.session.msg(u'pyerr', exc_content, dh.parent_header)
127 # Send exception info over pub socket for other clients than the caller
127 # Send exception info over pub socket for other clients than the caller
128 # to pick up
128 # to pick up
129 dh.pub_socket.send_json(exc_msg)
129 dh.pub_socket.send_json(exc_msg)
130
130
131 # FIXME - Hack: store exception info in shell object. Right now, the
131 # FIXME - Hack: store exception info in shell object. Right now, the
132 # caller is reading this info after the fact, we need to fix this logic
132 # caller is reading this info after the fact, we need to fix this logic
133 # to remove this hack. Even uglier, we need to store the error status
133 # to remove this hack. Even uglier, we need to store the error status
134 # here, because in the main loop, the logic that sets it is being
134 # here, because in the main loop, the logic that sets it is being
135 # skipped because runlines swallows the exceptions.
135 # skipped because runlines swallows the exceptions.
136 exc_content[u'status'] = u'error'
136 exc_content[u'status'] = u'error'
137 self._reply_content = exc_content
137 self._reply_content = exc_content
138 # /FIXME
138 # /FIXME
139
139
140 return exc_content
140 return exc_content
141
141
142 #------------------------------------------------------------------------
142 #------------------------------------------------------------------------
143 # Magic overrides
143 # Magic overrides
144 #------------------------------------------------------------------------
144 #------------------------------------------------------------------------
145 # Once the base class stops inheriting from magic, this code needs to be
145 # Once the base class stops inheriting from magic, this code needs to be
146 # moved into a separate machinery as well. For now, at least isolate here
146 # moved into a separate machinery as well. For now, at least isolate here
147 # the magics which this class needs to implement differently from the base
147 # the magics which this class needs to implement differently from the base
148 # class, or that are unique to it.
148 # class, or that are unique to it.
149
149
150 def magic_doctest_mode(self,parameter_s=''):
150 def magic_doctest_mode(self,parameter_s=''):
151 """Toggle doctest mode on and off.
151 """Toggle doctest mode on and off.
152
152
153 This mode is intended to make IPython behave as much as possible like a
153 This mode is intended to make IPython behave as much as possible like a
154 plain Python shell, from the perspective of how its prompts, exceptions
154 plain Python shell, from the perspective of how its prompts, exceptions
155 and output look. This makes it easy to copy and paste parts of a
155 and output look. This makes it easy to copy and paste parts of a
156 session into doctests. It does so by:
156 session into doctests. It does so by:
157
157
158 - Changing the prompts to the classic ``>>>`` ones.
158 - Changing the prompts to the classic ``>>>`` ones.
159 - Changing the exception reporting mode to 'Plain'.
159 - Changing the exception reporting mode to 'Plain'.
160 - Disabling pretty-printing of output.
160 - Disabling pretty-printing of output.
161
161
162 Note that IPython also supports the pasting of code snippets that have
162 Note that IPython also supports the pasting of code snippets that have
163 leading '>>>' and '...' prompts in them. This means that you can paste
163 leading '>>>' and '...' prompts in them. This means that you can paste
164 doctests from files or docstrings (even if they have leading
164 doctests from files or docstrings (even if they have leading
165 whitespace), and the code will execute correctly. You can then use
165 whitespace), and the code will execute correctly. You can then use
166 '%history -t' to see the translated history; this will give you the
166 '%history -t' to see the translated history; this will give you the
167 input after removal of all the leading prompts and whitespace, which
167 input after removal of all the leading prompts and whitespace, which
168 can be pasted back into an editor.
168 can be pasted back into an editor.
169
169
170 With these features, you can switch into this mode easily whenever you
170 With these features, you can switch into this mode easily whenever you
171 need to do testing and changes to doctests, without having to leave
171 need to do testing and changes to doctests, without having to leave
172 your existing IPython session.
172 your existing IPython session.
173 """
173 """
174
174
175 from IPython.utils.ipstruct import Struct
175 from IPython.utils.ipstruct import Struct
176
176
177 # Shorthands
177 # Shorthands
178 shell = self.shell
178 shell = self.shell
179 # dstore is a data store kept in the instance metadata bag to track any
179 # dstore is a data store kept in the instance metadata bag to track any
180 # changes we make, so we can undo them later.
180 # changes we make, so we can undo them later.
181 dstore = shell.meta.setdefault('doctest_mode', Struct())
181 dstore = shell.meta.setdefault('doctest_mode', Struct())
182 save_dstore = dstore.setdefault
182 save_dstore = dstore.setdefault
183
183
184 # save a few values we'll need to recover later
184 # save a few values we'll need to recover later
185 mode = save_dstore('mode', False)
185 mode = save_dstore('mode', False)
186 save_dstore('rc_pprint', shell.pprint)
186 save_dstore('rc_pprint', shell.pprint)
187 save_dstore('xmode', shell.InteractiveTB.mode)
187 save_dstore('xmode', shell.InteractiveTB.mode)
188
188
189 if mode == False:
189 if mode == False:
190 # turn on
190 # turn on
191 shell.pprint = False
191 shell.pprint = False
192 shell.magic_xmode('Plain')
192 shell.magic_xmode('Plain')
193 else:
193 else:
194 # turn off
194 # turn off
195 shell.pprint = dstore.rc_pprint
195 shell.pprint = dstore.rc_pprint
196 shell.magic_xmode(dstore.xmode)
196 shell.magic_xmode(dstore.xmode)
197
197
198 # Store new mode and inform on console
198 # Store new mode and inform on console
199 dstore.mode = bool(1-int(mode))
199 dstore.mode = bool(1-int(mode))
200 mode_label = ['OFF','ON'][dstore.mode]
200 mode_label = ['OFF','ON'][dstore.mode]
201 print('Doctest mode is:', mode_label)
201 print('Doctest mode is:', mode_label)
202
202
203 # Send the payload back so that clients can modify their prompt display
203 # Send the payload back so that clients can modify their prompt display
204 payload = dict(
204 payload = dict(
205 source='IPython.zmq.zmqshell.ZMQInteractiveShell.magic_doctest_mode',
205 source='IPython.zmq.zmqshell.ZMQInteractiveShell.magic_doctest_mode',
206 mode=dstore.mode)
206 mode=dstore.mode)
207 self.payload_manager.write_payload(payload)
207 self.payload_manager.write_payload(payload)
208
208
209 def magic_edit(self,parameter_s='',last_call=['','']):
209 def magic_edit(self,parameter_s='',last_call=['','']):
210 """Bring up an editor and execute the resulting code.
210 """Bring up an editor and execute the resulting code.
211
211
212 Usage:
212 Usage:
213 %edit [options] [args]
213 %edit [options] [args]
214
214
215 %edit runs IPython's editor hook. The default version of this hook is
215 %edit runs IPython's editor hook. The default version of this hook is
216 set to call the __IPYTHON__.rc.editor command. This is read from your
216 set to call the __IPYTHON__.rc.editor command. This is read from your
217 environment variable $EDITOR. If this isn't found, it will default to
217 environment variable $EDITOR. If this isn't found, it will default to
218 vi under Linux/Unix and to notepad under Windows. See the end of this
218 vi under Linux/Unix and to notepad under Windows. See the end of this
219 docstring for how to change the editor hook.
219 docstring for how to change the editor hook.
220
220
221 You can also set the value of this editor via the command line option
221 You can also set the value of this editor via the command line option
222 '-editor' or in your ipythonrc file. This is useful if you wish to use
222 '-editor' or in your ipythonrc file. This is useful if you wish to use
223 specifically for IPython an editor different from your typical default
223 specifically for IPython an editor different from your typical default
224 (and for Windows users who typically don't set environment variables).
224 (and for Windows users who typically don't set environment variables).
225
225
226 This command allows you to conveniently edit multi-line code right in
226 This command allows you to conveniently edit multi-line code right in
227 your IPython session.
227 your IPython session.
228
228
229 If called without arguments, %edit opens up an empty editor with a
229 If called without arguments, %edit opens up an empty editor with a
230 temporary file and will execute the contents of this file when you
230 temporary file and will execute the contents of this file when you
231 close it (don't forget to save it!).
231 close it (don't forget to save it!).
232
232
233
233
234 Options:
234 Options:
235
235
236 -n <number>: open the editor at a specified line number. By default,
236 -n <number>: open the editor at a specified line number. By default,
237 the IPython editor hook uses the unix syntax 'editor +N filename', but
237 the IPython editor hook uses the unix syntax 'editor +N filename', but
238 you can configure this by providing your own modified hook if your
238 you can configure this by providing your own modified hook if your
239 favorite editor supports line-number specifications with a different
239 favorite editor supports line-number specifications with a different
240 syntax.
240 syntax.
241
241
242 -p: this will call the editor with the same data as the previous time
242 -p: this will call the editor with the same data as the previous time
243 it was used, regardless of how long ago (in your current session) it
243 it was used, regardless of how long ago (in your current session) it
244 was.
244 was.
245
245
246 -r: use 'raw' input. This option only applies to input taken from the
246 -r: use 'raw' input. This option only applies to input taken from the
247 user's history. By default, the 'processed' history is used, so that
247 user's history. By default, the 'processed' history is used, so that
248 magics are loaded in their transformed version to valid Python. If
248 magics are loaded in their transformed version to valid Python. If
249 this option is given, the raw input as typed as the command line is
249 this option is given, the raw input as typed as the command line is
250 used instead. When you exit the editor, it will be executed by
250 used instead. When you exit the editor, it will be executed by
251 IPython's own processor.
251 IPython's own processor.
252
252
253 -x: do not execute the edited code immediately upon exit. This is
253 -x: do not execute the edited code immediately upon exit. This is
254 mainly useful if you are editing programs which need to be called with
254 mainly useful if you are editing programs which need to be called with
255 command line arguments, which you can then do using %run.
255 command line arguments, which you can then do using %run.
256
256
257
257
258 Arguments:
258 Arguments:
259
259
260 If arguments are given, the following possibilites exist:
260 If arguments are given, the following possibilites exist:
261
261
262 - The arguments are numbers or pairs of colon-separated numbers (like
262 - The arguments are numbers or pairs of colon-separated numbers (like
263 1 4:8 9). These are interpreted as lines of previous input to be
263 1 4:8 9). These are interpreted as lines of previous input to be
264 loaded into the editor. The syntax is the same of the %macro command.
264 loaded into the editor. The syntax is the same of the %macro command.
265
265
266 - If the argument doesn't start with a number, it is evaluated as a
266 - If the argument doesn't start with a number, it is evaluated as a
267 variable and its contents loaded into the editor. You can thus edit
267 variable and its contents loaded into the editor. You can thus edit
268 any string which contains python code (including the result of
268 any string which contains python code (including the result of
269 previous edits).
269 previous edits).
270
270
271 - If the argument is the name of an object (other than a string),
271 - If the argument is the name of an object (other than a string),
272 IPython will try to locate the file where it was defined and open the
272 IPython will try to locate the file where it was defined and open the
273 editor at the point where it is defined. You can use `%edit function`
273 editor at the point where it is defined. You can use `%edit function`
274 to load an editor exactly at the point where 'function' is defined,
274 to load an editor exactly at the point where 'function' is defined,
275 edit it and have the file be executed automatically.
275 edit it and have the file be executed automatically.
276
276
277 If the object is a macro (see %macro for details), this opens up your
277 If the object is a macro (see %macro for details), this opens up your
278 specified editor with a temporary file containing the macro's data.
278 specified editor with a temporary file containing the macro's data.
279 Upon exit, the macro is reloaded with the contents of the file.
279 Upon exit, the macro is reloaded with the contents of the file.
280
280
281 Note: opening at an exact line is only supported under Unix, and some
281 Note: opening at an exact line is only supported under Unix, and some
282 editors (like kedit and gedit up to Gnome 2.8) do not understand the
282 editors (like kedit and gedit up to Gnome 2.8) do not understand the
283 '+NUMBER' parameter necessary for this feature. Good editors like
283 '+NUMBER' parameter necessary for this feature. Good editors like
284 (X)Emacs, vi, jed, pico and joe all do.
284 (X)Emacs, vi, jed, pico and joe all do.
285
285
286 - If the argument is not found as a variable, IPython will look for a
286 - If the argument is not found as a variable, IPython will look for a
287 file with that name (adding .py if necessary) and load it into the
287 file with that name (adding .py if necessary) and load it into the
288 editor. It will execute its contents with execfile() when you exit,
288 editor. It will execute its contents with execfile() when you exit,
289 loading any code in the file into your interactive namespace.
289 loading any code in the file into your interactive namespace.
290
290
291 After executing your code, %edit will return as output the code you
291 After executing your code, %edit will return as output the code you
292 typed in the editor (except when it was an existing file). This way
292 typed in the editor (except when it was an existing file). This way
293 you can reload the code in further invocations of %edit as a variable,
293 you can reload the code in further invocations of %edit as a variable,
294 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
294 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
295 the output.
295 the output.
296
296
297 Note that %edit is also available through the alias %ed.
297 Note that %edit is also available through the alias %ed.
298
298
299 This is an example of creating a simple function inside the editor and
299 This is an example of creating a simple function inside the editor and
300 then modifying it. First, start up the editor:
300 then modifying it. First, start up the editor:
301
301
302 In [1]: ed
302 In [1]: ed
303 Editing... done. Executing edited code...
303 Editing... done. Executing edited code...
304 Out[1]: 'def foo():n print "foo() was defined in an editing session"n'
304 Out[1]: 'def foo():n print "foo() was defined in an editing session"n'
305
305
306 We can then call the function foo():
306 We can then call the function foo():
307
307
308 In [2]: foo()
308 In [2]: foo()
309 foo() was defined in an editing session
309 foo() was defined in an editing session
310
310
311 Now we edit foo. IPython automatically loads the editor with the
311 Now we edit foo. IPython automatically loads the editor with the
312 (temporary) file where foo() was previously defined:
312 (temporary) file where foo() was previously defined:
313
313
314 In [3]: ed foo
314 In [3]: ed foo
315 Editing... done. Executing edited code...
315 Editing... done. Executing edited code...
316
316
317 And if we call foo() again we get the modified version:
317 And if we call foo() again we get the modified version:
318
318
319 In [4]: foo()
319 In [4]: foo()
320 foo() has now been changed!
320 foo() has now been changed!
321
321
322 Here is an example of how to edit a code snippet successive
322 Here is an example of how to edit a code snippet successive
323 times. First we call the editor:
323 times. First we call the editor:
324
324
325 In [5]: ed
325 In [5]: ed
326 Editing... done. Executing edited code...
326 Editing... done. Executing edited code...
327 hello
327 hello
328 Out[5]: "print 'hello'n"
328 Out[5]: "print 'hello'n"
329
329
330 Now we call it again with the previous output (stored in _):
330 Now we call it again with the previous output (stored in _):
331
331
332 In [6]: ed _
332 In [6]: ed _
333 Editing... done. Executing edited code...
333 Editing... done. Executing edited code...
334 hello world
334 hello world
335 Out[6]: "print 'hello world'n"
335 Out[6]: "print 'hello world'n"
336
336
337 Now we call it with the output #8 (stored in _8, also as Out[8]):
337 Now we call it with the output #8 (stored in _8, also as Out[8]):
338
338
339 In [7]: ed _8
339 In [7]: ed _8
340 Editing... done. Executing edited code...
340 Editing... done. Executing edited code...
341 hello again
341 hello again
342 Out[7]: "print 'hello again'n"
342 Out[7]: "print 'hello again'n"
343
343
344
344
345 Changing the default editor hook:
345 Changing the default editor hook:
346
346
347 If you wish to write your own editor hook, you can put it in a
347 If you wish to write your own editor hook, you can put it in a
348 configuration file which you load at startup time. The default hook
348 configuration file which you load at startup time. The default hook
349 is defined in the IPython.core.hooks module, and you can use that as a
349 is defined in the IPython.core.hooks module, and you can use that as a
350 starting example for further modifications. That file also has
350 starting example for further modifications. That file also has
351 general instructions on how to set a new hook for use once you've
351 general instructions on how to set a new hook for use once you've
352 defined it."""
352 defined it."""
353
353
354 # FIXME: This function has become a convoluted mess. It needs a
354 # FIXME: This function has become a convoluted mess. It needs a
355 # ground-up rewrite with clean, simple logic.
355 # ground-up rewrite with clean, simple logic.
356
356
357 def make_filename(arg):
357 def make_filename(arg):
358 "Make a filename from the given args"
358 "Make a filename from the given args"
359 try:
359 try:
360 filename = get_py_filename(arg)
360 filename = get_py_filename(arg)
361 except IOError:
361 except IOError:
362 if args.endswith('.py'):
362 if args.endswith('.py'):
363 filename = arg
363 filename = arg
364 else:
364 else:
365 filename = None
365 filename = None
366 return filename
366 return filename
367
367
368 # custom exceptions
368 # custom exceptions
369 class DataIsObject(Exception): pass
369 class DataIsObject(Exception): pass
370
370
371 opts,args = self.parse_options(parameter_s,'prn:')
371 opts,args = self.parse_options(parameter_s,'prn:')
372 # Set a few locals from the options for convenience:
372 # Set a few locals from the options for convenience:
373 opts_p = opts.has_key('p')
373 opts_p = opts.has_key('p')
374 opts_r = opts.has_key('r')
374 opts_r = opts.has_key('r')
375
375
376 # Default line number value
376 # Default line number value
377 lineno = opts.get('n',None)
377 lineno = opts.get('n',None)
378 if lineno is not None:
378 if lineno is not None:
379 try:
379 try:
380 lineno = int(lineno)
380 lineno = int(lineno)
381 except:
381 except:
382 warn("The -n argument must be an integer.")
382 warn("The -n argument must be an integer.")
383 return
383 return
384
384
385 if opts_p:
385 if opts_p:
386 args = '_%s' % last_call[0]
386 args = '_%s' % last_call[0]
387 if not self.shell.user_ns.has_key(args):
387 if not self.shell.user_ns.has_key(args):
388 args = last_call[1]
388 args = last_call[1]
389
389
390 # use last_call to remember the state of the previous call, but don't
390 # use last_call to remember the state of the previous call, but don't
391 # let it be clobbered by successive '-p' calls.
391 # let it be clobbered by successive '-p' calls.
392 try:
392 try:
393 last_call[0] = self.shell.displayhook.prompt_count
393 last_call[0] = self.shell.displayhook.prompt_count
394 if not opts_p:
394 if not opts_p:
395 last_call[1] = parameter_s
395 last_call[1] = parameter_s
396 except:
396 except:
397 pass
397 pass
398
398
399 # by default this is done with temp files, except when the given
399 # by default this is done with temp files, except when the given
400 # arg is a filename
400 # arg is a filename
401 use_temp = 1
401 use_temp = 1
402
402
403 if re.match(r'\d',args):
403 if re.match(r'\d',args):
404 # Mode where user specifies ranges of lines, like in %macro.
404 # Mode where user specifies ranges of lines, like in %macro.
405 # This means that you can't edit files whose names begin with
405 # This means that you can't edit files whose names begin with
406 # numbers this way. Tough.
406 # numbers this way. Tough.
407 ranges = args.split()
407 ranges = args.split()
408 data = ''.join(self.extract_input_slices(ranges,opts_r))
408 data = ''.join(self.extract_input_slices(ranges,opts_r))
409 elif args.endswith('.py'):
409 elif args.endswith('.py'):
410 filename = make_filename(args)
410 filename = make_filename(args)
411 data = ''
411 data = ''
412 use_temp = 0
412 use_temp = 0
413 elif args:
413 elif args:
414 try:
414 try:
415 # Load the parameter given as a variable. If not a string,
415 # Load the parameter given as a variable. If not a string,
416 # process it as an object instead (below)
416 # process it as an object instead (below)
417
417
418 #print '*** args',args,'type',type(args) # dbg
418 #print '*** args',args,'type',type(args) # dbg
419 data = eval(args,self.shell.user_ns)
419 data = eval(args,self.shell.user_ns)
420 if not type(data) in StringTypes:
420 if not type(data) in StringTypes:
421 raise DataIsObject
421 raise DataIsObject
422
422
423 except (NameError,SyntaxError):
423 except (NameError,SyntaxError):
424 # given argument is not a variable, try as a filename
424 # given argument is not a variable, try as a filename
425 filename = make_filename(args)
425 filename = make_filename(args)
426 if filename is None:
426 if filename is None:
427 warn("Argument given (%s) can't be found as a variable "
427 warn("Argument given (%s) can't be found as a variable "
428 "or as a filename." % args)
428 "or as a filename." % args)
429 return
429 return
430
430
431 data = ''
431 data = ''
432 use_temp = 0
432 use_temp = 0
433 except DataIsObject:
433 except DataIsObject:
434
434
435 # macros have a special edit function
435 # macros have a special edit function
436 if isinstance(data,Macro):
436 if isinstance(data,Macro):
437 self._edit_macro(args,data)
437 self._edit_macro(args,data)
438 return
438 return
439
439
440 # For objects, try to edit the file where they are defined
440 # For objects, try to edit the file where they are defined
441 try:
441 try:
442 filename = inspect.getabsfile(data)
442 filename = inspect.getabsfile(data)
443 if 'fakemodule' in filename.lower() and inspect.isclass(data):
443 if 'fakemodule' in filename.lower() and inspect.isclass(data):
444 # class created by %edit? Try to find source
444 # class created by %edit? Try to find source
445 # by looking for method definitions instead, the
445 # by looking for method definitions instead, the
446 # __module__ in those classes is FakeModule.
446 # __module__ in those classes is FakeModule.
447 attrs = [getattr(data, aname) for aname in dir(data)]
447 attrs = [getattr(data, aname) for aname in dir(data)]
448 for attr in attrs:
448 for attr in attrs:
449 if not inspect.ismethod(attr):
449 if not inspect.ismethod(attr):
450 continue
450 continue
451 filename = inspect.getabsfile(attr)
451 filename = inspect.getabsfile(attr)
452 if filename and 'fakemodule' not in filename.lower():
452 if filename and 'fakemodule' not in filename.lower():
453 # change the attribute to be the edit target instead
453 # change the attribute to be the edit target instead
454 data = attr
454 data = attr
455 break
455 break
456
456
457 datafile = 1
457 datafile = 1
458 except TypeError:
458 except TypeError:
459 filename = make_filename(args)
459 filename = make_filename(args)
460 datafile = 1
460 datafile = 1
461 warn('Could not find file where `%s` is defined.\n'
461 warn('Could not find file where `%s` is defined.\n'
462 'Opening a file named `%s`' % (args,filename))
462 'Opening a file named `%s`' % (args,filename))
463 # Now, make sure we can actually read the source (if it was in
463 # Now, make sure we can actually read the source (if it was in
464 # a temp file it's gone by now).
464 # a temp file it's gone by now).
465 if datafile:
465 if datafile:
466 try:
466 try:
467 if lineno is None:
467 if lineno is None:
468 lineno = inspect.getsourcelines(data)[1]
468 lineno = inspect.getsourcelines(data)[1]
469 except IOError:
469 except IOError:
470 filename = make_filename(args)
470 filename = make_filename(args)
471 if filename is None:
471 if filename is None:
472 warn('The file `%s` where `%s` was defined cannot '
472 warn('The file `%s` where `%s` was defined cannot '
473 'be read.' % (filename,data))
473 'be read.' % (filename,data))
474 return
474 return
475 use_temp = 0
475 use_temp = 0
476 else:
476 else:
477 data = ''
477 data = ''
478
478
479 if use_temp:
479 if use_temp:
480 filename = self.shell.mktempfile(data)
480 filename = self.shell.mktempfile(data)
481 print('IPython will make a temporary file named:', filename)
481 print('IPython will make a temporary file named:', filename)
482
482
483 # Make sure we send to the client an absolute path, in case the working
483 # Make sure we send to the client an absolute path, in case the working
484 # directory of client and kernel don't match
484 # directory of client and kernel don't match
485 filename = os.path.abspath(filename)
485 filename = os.path.abspath(filename)
486
486
487 payload = {
487 payload = {
488 'source' : 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic',
488 'source' : 'IPython.zmq.zmqshell.ZMQInteractiveShell.edit_magic',
489 'filename' : filename,
489 'filename' : filename,
490 'line_number' : lineno
490 'line_number' : lineno
491 }
491 }
492 self.payload_manager.write_payload(payload)
492 self.payload_manager.write_payload(payload)
493
493
494 def magic_gui(self, *args, **kwargs):
494 def magic_gui(self, *args, **kwargs):
495 raise NotImplementedError(
495 raise NotImplementedError(
496 'GUI support must be enabled in command line options.')
496 'GUI support must be enabled in command line options.')
497
497
498 def magic_pylab(self, *args, **kwargs):
498 def magic_pylab(self, *args, **kwargs):
499 raise NotImplementedError(
499 raise NotImplementedError(
500 'pylab support must be enabled in command line options.')
500 'pylab support must be enabled in command line options.')
501
501
502 # A few magics that are adapted to the specifics of using pexpect and a
502 # A few magics that are adapted to the specifics of using pexpect and a
503 # remote terminal
503 # remote terminal
504
504
505 def magic_clear(self, arg_s):
505 def magic_clear(self, arg_s):
506 """Clear the terminal."""
506 """Clear the terminal."""
507 if os.name == 'posix':
507 if os.name == 'posix':
508 self.shell.system("clear")
508 self.shell.system("clear")
509 else:
509 else:
510 self.shell.system("cls")
510 self.shell.system("cls")
511
511
512 if os.name == 'nt':
512 if os.name == 'nt':
513 # This is the usual name in windows
513 # This is the usual name in windows
514 magic_cls = magic_clear
514 magic_cls = magic_clear
515
515
516 # Terminal pagers won't work over pexpect, but we do have our own pager
516 # Terminal pagers won't work over pexpect, but we do have our own pager
517
517
518 def magic_less(self, arg_s):
518 def magic_less(self, arg_s):
519 """Show a file through the pager.
519 """Show a file through the pager.
520
520
521 Files ending in .py are syntax-highlighted."""
521 Files ending in .py are syntax-highlighted."""
522 cont = open(arg_s).read()
522 cont = open(arg_s).read()
523 if arg_s.endswith('.py'):
523 if arg_s.endswith('.py'):
524 cont = self.shell.pycolorize(cont)
524 cont = self.shell.pycolorize(cont)
525 page.page(cont)
525 page.page(cont)
526
526
527 magic_more = magic_less
527 magic_more = magic_less
528
528
529 # Man calls a pager, so we also need to redefine it
529 # Man calls a pager, so we also need to redefine it
530 if os.name == 'posix':
530 if os.name == 'posix':
531 def magic_man(self, arg_s):
531 def magic_man(self, arg_s):
532 """Find the man page for the given command and display in pager."""
532 """Find the man page for the given command and display in pager."""
533 page.page(self.shell.getoutput('man %s' % arg_s, split=False))
533 page.page(self.shell.getoutput('man %s | col -b' % arg_s,
534 split=False))
534
535
535 # FIXME: this is specific to the GUI, so we should let the gui app load
536 # FIXME: this is specific to the GUI, so we should let the gui app load
536 # magics at startup that are only for the gui. Once the gui app has proper
537 # magics at startup that are only for the gui. Once the gui app has proper
537 # profile and configuration management, we can have it initialize a kernel
538 # profile and configuration management, we can have it initialize a kernel
538 # with a special config file that provides these.
539 # with a special config file that provides these.
539 def magic_guiref(self, arg_s):
540 def magic_guiref(self, arg_s):
540 """Show a basic reference about the GUI console."""
541 """Show a basic reference about the GUI console."""
541 from IPython.core.usage import gui_reference
542 from IPython.core.usage import gui_reference
542 page.page(gui_reference, auto_html=True)
543 page.page(gui_reference, auto_html=True)
543
544
544
545
545 InteractiveShellABC.register(ZMQInteractiveShell)
546 InteractiveShellABC.register(ZMQInteractiveShell)
General Comments 0
You need to be logged in to leave comments. Login now