##// END OF EJS Templates
Remove unused imports in IPython.terminal
Thomas Kluyver -
Show More
@@ -1,157 +1,152 b''
1 """ A minimal application using the ZMQ-based terminal IPython frontend.
1 """ A minimal application using the ZMQ-based terminal IPython frontend.
2
2
3 This is not a complete console app, as subprocess will not be able to receive
3 This is not a complete console app, as subprocess will not be able to receive
4 input, there is no real readline support, among other limitations.
4 input, there is no real readline support, among other limitations.
5
5
6 Authors:
6 Authors:
7
7
8 * Min RK
8 * Min RK
9 * Paul Ivanov
9 * Paul Ivanov
10
10
11 """
11 """
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 import signal
16 import signal
17 import sys
18 import time
19
17
20 from IPython.terminal.ipapp import TerminalIPythonApp, frontend_flags as term_flags
18 from IPython.terminal.ipapp import TerminalIPythonApp, frontend_flags as term_flags
21
19
22 from IPython.utils.traitlets import (
20 from IPython.utils.traitlets import (
23 Dict, List, Unicode, Int, CaselessStrEnum, CBool, Any
21 Dict, Any
24 )
22 )
25 from IPython.utils.warn import warn,error
23 from IPython.utils.warn import error
26
24
27 from IPython.kernel.zmq.kernelapp import IPKernelApp
28 from IPython.kernel.zmq.session import Session, default_secure
29 from IPython.kernel.zmq.zmqshell import ZMQInteractiveShell
30 from IPython.consoleapp import (
25 from IPython.consoleapp import (
31 IPythonConsoleApp, app_aliases, app_flags, aliases, app_aliases, flags
26 IPythonConsoleApp, app_aliases, app_flags, aliases, flags
32 )
27 )
33
28
34 from IPython.terminal.console.interactiveshell import ZMQTerminalInteractiveShell
29 from IPython.terminal.console.interactiveshell import ZMQTerminalInteractiveShell
35
30
36 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
37 # Globals
32 # Globals
38 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
39
34
40 _examples = """
35 _examples = """
41 ipython console # start the ZMQ-based console
36 ipython console # start the ZMQ-based console
42 ipython console --existing # connect to an existing ipython session
37 ipython console --existing # connect to an existing ipython session
43 """
38 """
44
39
45 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
46 # Flags and Aliases
41 # Flags and Aliases
47 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
48
43
49 # copy flags from mixin:
44 # copy flags from mixin:
50 flags = dict(flags)
45 flags = dict(flags)
51 # start with mixin frontend flags:
46 # start with mixin frontend flags:
52 frontend_flags = dict(app_flags)
47 frontend_flags = dict(app_flags)
53 # add TerminalIPApp flags:
48 # add TerminalIPApp flags:
54 frontend_flags.update(term_flags)
49 frontend_flags.update(term_flags)
55 # disable quick startup, as it won't propagate to the kernel anyway
50 # disable quick startup, as it won't propagate to the kernel anyway
56 frontend_flags.pop('quick')
51 frontend_flags.pop('quick')
57 # update full dict with frontend flags:
52 # update full dict with frontend flags:
58 flags.update(frontend_flags)
53 flags.update(frontend_flags)
59
54
60 # copy flags from mixin
55 # copy flags from mixin
61 aliases = dict(aliases)
56 aliases = dict(aliases)
62 # start with mixin frontend flags
57 # start with mixin frontend flags
63 frontend_aliases = dict(app_aliases)
58 frontend_aliases = dict(app_aliases)
64 # load updated frontend flags into full dict
59 # load updated frontend flags into full dict
65 aliases.update(frontend_aliases)
60 aliases.update(frontend_aliases)
66
61
67 # get flags&aliases into sets, and remove a couple that
62 # get flags&aliases into sets, and remove a couple that
68 # shouldn't be scrubbed from backend flags:
63 # shouldn't be scrubbed from backend flags:
69 frontend_aliases = set(frontend_aliases.keys())
64 frontend_aliases = set(frontend_aliases.keys())
70 frontend_flags = set(frontend_flags.keys())
65 frontend_flags = set(frontend_flags.keys())
71
66
72
67
73 #-----------------------------------------------------------------------------
68 #-----------------------------------------------------------------------------
74 # Classes
69 # Classes
75 #-----------------------------------------------------------------------------
70 #-----------------------------------------------------------------------------
76
71
77
72
78 class ZMQTerminalIPythonApp(TerminalIPythonApp, IPythonConsoleApp):
73 class ZMQTerminalIPythonApp(TerminalIPythonApp, IPythonConsoleApp):
79 name = "ipython-console"
74 name = "ipython-console"
80 """Start a terminal frontend to the IPython zmq kernel."""
75 """Start a terminal frontend to the IPython zmq kernel."""
81
76
82 description = """
77 description = """
83 The IPython terminal-based Console.
78 The IPython terminal-based Console.
84
79
85 This launches a Console application inside a terminal.
80 This launches a Console application inside a terminal.
86
81
87 The Console supports various extra features beyond the traditional
82 The Console supports various extra features beyond the traditional
88 single-process Terminal IPython shell, such as connecting to an
83 single-process Terminal IPython shell, such as connecting to an
89 existing ipython session, via:
84 existing ipython session, via:
90
85
91 ipython console --existing
86 ipython console --existing
92
87
93 where the previous session could have been created by another ipython
88 where the previous session could have been created by another ipython
94 console, an ipython qtconsole, or by opening an ipython notebook.
89 console, an ipython qtconsole, or by opening an ipython notebook.
95
90
96 """
91 """
97 examples = _examples
92 examples = _examples
98
93
99 classes = [ZMQTerminalInteractiveShell] + IPythonConsoleApp.classes
94 classes = [ZMQTerminalInteractiveShell] + IPythonConsoleApp.classes
100 flags = Dict(flags)
95 flags = Dict(flags)
101 aliases = Dict(aliases)
96 aliases = Dict(aliases)
102 frontend_aliases = Any(frontend_aliases)
97 frontend_aliases = Any(frontend_aliases)
103 frontend_flags = Any(frontend_flags)
98 frontend_flags = Any(frontend_flags)
104
99
105 subcommands = Dict()
100 subcommands = Dict()
106
101
107 def parse_command_line(self, argv=None):
102 def parse_command_line(self, argv=None):
108 super(ZMQTerminalIPythonApp, self).parse_command_line(argv)
103 super(ZMQTerminalIPythonApp, self).parse_command_line(argv)
109 self.build_kernel_argv(argv)
104 self.build_kernel_argv(argv)
110
105
111 def init_shell(self):
106 def init_shell(self):
112 IPythonConsoleApp.initialize(self)
107 IPythonConsoleApp.initialize(self)
113 # relay sigint to kernel
108 # relay sigint to kernel
114 signal.signal(signal.SIGINT, self.handle_sigint)
109 signal.signal(signal.SIGINT, self.handle_sigint)
115 self.shell = ZMQTerminalInteractiveShell.instance(parent=self,
110 self.shell = ZMQTerminalInteractiveShell.instance(parent=self,
116 display_banner=False, profile_dir=self.profile_dir,
111 display_banner=False, profile_dir=self.profile_dir,
117 ipython_dir=self.ipython_dir,
112 ipython_dir=self.ipython_dir,
118 manager=self.kernel_manager,
113 manager=self.kernel_manager,
119 client=self.kernel_client,
114 client=self.kernel_client,
120 )
115 )
121
116
122 def init_gui_pylab(self):
117 def init_gui_pylab(self):
123 # no-op, because we don't want to import matplotlib in the frontend.
118 # no-op, because we don't want to import matplotlib in the frontend.
124 pass
119 pass
125
120
126 def handle_sigint(self, *args):
121 def handle_sigint(self, *args):
127 if self.shell._executing:
122 if self.shell._executing:
128 if self.kernel_manager:
123 if self.kernel_manager:
129 # interrupt already gets passed to subprocess by signal handler.
124 # interrupt already gets passed to subprocess by signal handler.
130 # Only if we prevent that should we need to explicitly call
125 # Only if we prevent that should we need to explicitly call
131 # interrupt_kernel, until which time, this would result in a
126 # interrupt_kernel, until which time, this would result in a
132 # double-interrupt:
127 # double-interrupt:
133 # self.kernel_manager.interrupt_kernel()
128 # self.kernel_manager.interrupt_kernel()
134 pass
129 pass
135 else:
130 else:
136 self.shell.write_err('\n')
131 self.shell.write_err('\n')
137 error("Cannot interrupt kernels we didn't start.\n")
132 error("Cannot interrupt kernels we didn't start.\n")
138 else:
133 else:
139 # raise the KeyboardInterrupt if we aren't waiting for execution,
134 # raise the KeyboardInterrupt if we aren't waiting for execution,
140 # so that the interact loop advances, and prompt is redrawn, etc.
135 # so that the interact loop advances, and prompt is redrawn, etc.
141 raise KeyboardInterrupt
136 raise KeyboardInterrupt
142
137
143
138
144 def init_code(self):
139 def init_code(self):
145 # no-op in the frontend, code gets run in the backend
140 # no-op in the frontend, code gets run in the backend
146 pass
141 pass
147
142
148 def launch_new_instance():
143 def launch_new_instance():
149 """Create and run a full blown IPython instance"""
144 """Create and run a full blown IPython instance"""
150 app = ZMQTerminalIPythonApp.instance()
145 app = ZMQTerminalIPythonApp.instance()
151 app.initialize()
146 app.initialize()
152 app.start()
147 app.start()
153
148
154
149
155 if __name__ == '__main__':
150 if __name__ == '__main__':
156 launch_new_instance()
151 launch_new_instance()
157
152
@@ -1,465 +1,464 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """terminal client to the IPython kernel
2 """terminal client to the IPython kernel
3
3
4 """
4 """
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 # Copyright (C) 2013 The IPython Development Team
6 # Copyright (C) 2013 The IPython Development Team
7 #
7 #
8 # Distributed under the terms of the BSD License. The full license is in
8 # Distributed under the terms of the BSD License. The full license is in
9 # the file COPYING, distributed as part of this software.
9 # the file COPYING, distributed as part of this software.
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11
11
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Imports
13 # Imports
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 from __future__ import print_function
15 from __future__ import print_function
16
16
17 import bdb
17 import bdb
18 import signal
18 import signal
19 import os
19 import os
20 import sys
20 import sys
21 import time
21 import time
22 import subprocess
22 import subprocess
23 from io import BytesIO
23 from io import BytesIO
24 import base64
24 import base64
25
25
26 from Queue import Empty
26 from Queue import Empty
27
27
28 try:
28 try:
29 from contextlib import nested
29 from contextlib import nested
30 except:
30 except:
31 from IPython.utils.nested_context import nested
31 from IPython.utils.nested_context import nested
32
32
33 from IPython.core.alias import AliasManager, AliasError
34 from IPython.core import page
33 from IPython.core import page
35 from IPython.utils.warn import warn, error, fatal
34 from IPython.utils.warn import warn, error
36 from IPython.utils import io
35 from IPython.utils import io
37 from IPython.utils.traitlets import List, Enum, Any, Instance, Unicode
36 from IPython.utils.traitlets import List, Enum, Any, Instance, Unicode
38 from IPython.utils.tempdir import NamedFileInTemporaryDirectory
37 from IPython.utils.tempdir import NamedFileInTemporaryDirectory
39
38
40 from IPython.terminal.interactiveshell import TerminalInteractiveShell
39 from IPython.terminal.interactiveshell import TerminalInteractiveShell
41 from IPython.terminal.console.completer import ZMQCompleter
40 from IPython.terminal.console.completer import ZMQCompleter
42
41
43
42
44 class ZMQTerminalInteractiveShell(TerminalInteractiveShell):
43 class ZMQTerminalInteractiveShell(TerminalInteractiveShell):
45 """A subclass of TerminalInteractiveShell that uses the 0MQ kernel"""
44 """A subclass of TerminalInteractiveShell that uses the 0MQ kernel"""
46 _executing = False
45 _executing = False
47
46
48 image_handler = Enum(('PIL', 'stream', 'tempfile', 'callable'),
47 image_handler = Enum(('PIL', 'stream', 'tempfile', 'callable'),
49 config=True, help=
48 config=True, help=
50 """
49 """
51 Handler for image type output. This is useful, for example,
50 Handler for image type output. This is useful, for example,
52 when connecting to the kernel in which pylab inline backend is
51 when connecting to the kernel in which pylab inline backend is
53 activated. There are four handlers defined. 'PIL': Use
52 activated. There are four handlers defined. 'PIL': Use
54 Python Imaging Library to popup image; 'stream': Use an
53 Python Imaging Library to popup image; 'stream': Use an
55 external program to show the image. Image will be fed into
54 external program to show the image. Image will be fed into
56 the STDIN of the program. You will need to configure
55 the STDIN of the program. You will need to configure
57 `stream_image_handler`; 'tempfile': Use an external program to
56 `stream_image_handler`; 'tempfile': Use an external program to
58 show the image. Image will be saved in a temporally file and
57 show the image. Image will be saved in a temporally file and
59 the program is called with the temporally file. You will need
58 the program is called with the temporally file. You will need
60 to configure `tempfile_image_handler`; 'callable': You can set
59 to configure `tempfile_image_handler`; 'callable': You can set
61 any Python callable which is called with the image data. You
60 any Python callable which is called with the image data. You
62 will need to configure `callable_image_handler`.
61 will need to configure `callable_image_handler`.
63 """
62 """
64 )
63 )
65
64
66 stream_image_handler = List(config=True, help=
65 stream_image_handler = List(config=True, help=
67 """
66 """
68 Command to invoke an image viewer program when you are using
67 Command to invoke an image viewer program when you are using
69 'stream' image handler. This option is a list of string where
68 'stream' image handler. This option is a list of string where
70 the first element is the command itself and reminders are the
69 the first element is the command itself and reminders are the
71 options for the command. Raw image data is given as STDIN to
70 options for the command. Raw image data is given as STDIN to
72 the program.
71 the program.
73 """
72 """
74 )
73 )
75
74
76 tempfile_image_handler = List(config=True, help=
75 tempfile_image_handler = List(config=True, help=
77 """
76 """
78 Command to invoke an image viewer program when you are using
77 Command to invoke an image viewer program when you are using
79 'tempfile' image handler. This option is a list of string
78 'tempfile' image handler. This option is a list of string
80 where the first element is the command itself and reminders
79 where the first element is the command itself and reminders
81 are the options for the command. You can use {file} and
80 are the options for the command. You can use {file} and
82 {format} in the string to represent the location of the
81 {format} in the string to represent the location of the
83 generated image file and image format.
82 generated image file and image format.
84 """
83 """
85 )
84 )
86
85
87 callable_image_handler = Any(config=True, help=
86 callable_image_handler = Any(config=True, help=
88 """
87 """
89 Callable object called via 'callable' image handler with one
88 Callable object called via 'callable' image handler with one
90 argument, `data`, which is `msg["content"]["data"]` where
89 argument, `data`, which is `msg["content"]["data"]` where
91 `msg` is the message from iopub channel. For exmaple, you can
90 `msg` is the message from iopub channel. For exmaple, you can
92 find base64 encoded PNG data as `data['image/png']`.
91 find base64 encoded PNG data as `data['image/png']`.
93 """
92 """
94 )
93 )
95
94
96 mime_preference = List(
95 mime_preference = List(
97 default_value=['image/png', 'image/jpeg', 'image/svg+xml'],
96 default_value=['image/png', 'image/jpeg', 'image/svg+xml'],
98 config=True, allow_none=False, help=
97 config=True, allow_none=False, help=
99 """
98 """
100 Preferred object representation MIME type in order. First
99 Preferred object representation MIME type in order. First
101 matched MIME type will be used.
100 matched MIME type will be used.
102 """
101 """
103 )
102 )
104
103
105 manager = Instance('IPython.kernel.KernelManager')
104 manager = Instance('IPython.kernel.KernelManager')
106 client = Instance('IPython.kernel.KernelClient')
105 client = Instance('IPython.kernel.KernelClient')
107 def _client_changed(self, name, old, new):
106 def _client_changed(self, name, old, new):
108 self.session_id = new.session.session
107 self.session_id = new.session.session
109 session_id = Unicode()
108 session_id = Unicode()
110
109
111 def init_completer(self):
110 def init_completer(self):
112 """Initialize the completion machinery.
111 """Initialize the completion machinery.
113
112
114 This creates completion machinery that can be used by client code,
113 This creates completion machinery that can be used by client code,
115 either interactively in-process (typically triggered by the readline
114 either interactively in-process (typically triggered by the readline
116 library), programatically (such as in test suites) or out-of-prcess
115 library), programatically (such as in test suites) or out-of-prcess
117 (typically over the network by remote frontends).
116 (typically over the network by remote frontends).
118 """
117 """
119 from IPython.core.completerlib import (module_completer,
118 from IPython.core.completerlib import (module_completer,
120 magic_run_completer, cd_completer)
119 magic_run_completer, cd_completer)
121
120
122 self.Completer = ZMQCompleter(self, self.client)
121 self.Completer = ZMQCompleter(self, self.client)
123
122
124
123
125 self.set_hook('complete_command', module_completer, str_key = 'import')
124 self.set_hook('complete_command', module_completer, str_key = 'import')
126 self.set_hook('complete_command', module_completer, str_key = 'from')
125 self.set_hook('complete_command', module_completer, str_key = 'from')
127 self.set_hook('complete_command', magic_run_completer, str_key = '%run')
126 self.set_hook('complete_command', magic_run_completer, str_key = '%run')
128 self.set_hook('complete_command', cd_completer, str_key = '%cd')
127 self.set_hook('complete_command', cd_completer, str_key = '%cd')
129
128
130 # Only configure readline if we truly are using readline. IPython can
129 # Only configure readline if we truly are using readline. IPython can
131 # do tab-completion over the network, in GUIs, etc, where readline
130 # do tab-completion over the network, in GUIs, etc, where readline
132 # itself may be absent
131 # itself may be absent
133 if self.has_readline:
132 if self.has_readline:
134 self.set_readline_completer()
133 self.set_readline_completer()
135
134
136 def run_cell(self, cell, store_history=True):
135 def run_cell(self, cell, store_history=True):
137 """Run a complete IPython cell.
136 """Run a complete IPython cell.
138
137
139 Parameters
138 Parameters
140 ----------
139 ----------
141 cell : str
140 cell : str
142 The code (including IPython code such as %magic functions) to run.
141 The code (including IPython code such as %magic functions) to run.
143 store_history : bool
142 store_history : bool
144 If True, the raw and translated cell will be stored in IPython's
143 If True, the raw and translated cell will be stored in IPython's
145 history. For user code calling back into IPython's machinery, this
144 history. For user code calling back into IPython's machinery, this
146 should be set to False.
145 should be set to False.
147 """
146 """
148 if (not cell) or cell.isspace():
147 if (not cell) or cell.isspace():
149 return
148 return
150
149
151 if cell.strip() == 'exit':
150 if cell.strip() == 'exit':
152 # explicitly handle 'exit' command
151 # explicitly handle 'exit' command
153 return self.ask_exit()
152 return self.ask_exit()
154
153
155 self._executing = True
154 self._executing = True
156 # flush stale replies, which could have been ignored, due to missed heartbeats
155 # flush stale replies, which could have been ignored, due to missed heartbeats
157 while self.client.shell_channel.msg_ready():
156 while self.client.shell_channel.msg_ready():
158 self.client.shell_channel.get_msg()
157 self.client.shell_channel.get_msg()
159 # shell_channel.execute takes 'hidden', which is the inverse of store_hist
158 # shell_channel.execute takes 'hidden', which is the inverse of store_hist
160 msg_id = self.client.shell_channel.execute(cell, not store_history)
159 msg_id = self.client.shell_channel.execute(cell, not store_history)
161 while not self.client.shell_channel.msg_ready() and self.client.is_alive():
160 while not self.client.shell_channel.msg_ready() and self.client.is_alive():
162 try:
161 try:
163 self.handle_stdin_request(timeout=0.05)
162 self.handle_stdin_request(timeout=0.05)
164 except Empty:
163 except Empty:
165 # display intermediate print statements, etc.
164 # display intermediate print statements, etc.
166 self.handle_iopub()
165 self.handle_iopub()
167 pass
166 pass
168 if self.client.shell_channel.msg_ready():
167 if self.client.shell_channel.msg_ready():
169 self.handle_execute_reply(msg_id)
168 self.handle_execute_reply(msg_id)
170 self._executing = False
169 self._executing = False
171
170
172 #-----------------
171 #-----------------
173 # message handlers
172 # message handlers
174 #-----------------
173 #-----------------
175
174
176 def handle_execute_reply(self, msg_id):
175 def handle_execute_reply(self, msg_id):
177 msg = self.client.shell_channel.get_msg()
176 msg = self.client.shell_channel.get_msg()
178 if msg["parent_header"].get("msg_id", None) == msg_id:
177 if msg["parent_header"].get("msg_id", None) == msg_id:
179
178
180 self.handle_iopub()
179 self.handle_iopub()
181
180
182 content = msg["content"]
181 content = msg["content"]
183 status = content['status']
182 status = content['status']
184
183
185 if status == 'aborted':
184 if status == 'aborted':
186 self.write('Aborted\n')
185 self.write('Aborted\n')
187 return
186 return
188 elif status == 'ok':
187 elif status == 'ok':
189 # print execution payloads as well:
188 # print execution payloads as well:
190 for item in content["payload"]:
189 for item in content["payload"]:
191 text = item.get('text', None)
190 text = item.get('text', None)
192 if text:
191 if text:
193 page.page(text)
192 page.page(text)
194
193
195 elif status == 'error':
194 elif status == 'error':
196 for frame in content["traceback"]:
195 for frame in content["traceback"]:
197 print(frame, file=io.stderr)
196 print(frame, file=io.stderr)
198
197
199 self.execution_count = int(content["execution_count"] + 1)
198 self.execution_count = int(content["execution_count"] + 1)
200
199
201
200
202 def handle_iopub(self):
201 def handle_iopub(self):
203 """ Method to procces subscribe channel's messages
202 """ Method to procces subscribe channel's messages
204
203
205 This method reads a message and processes the content in different
204 This method reads a message and processes the content in different
206 outputs like stdout, stderr, pyout and status
205 outputs like stdout, stderr, pyout and status
207
206
208 Arguments:
207 Arguments:
209 sub_msg: message receive from kernel in the sub socket channel
208 sub_msg: message receive from kernel in the sub socket channel
210 capture by kernel manager.
209 capture by kernel manager.
211 """
210 """
212 while self.client.iopub_channel.msg_ready():
211 while self.client.iopub_channel.msg_ready():
213 sub_msg = self.client.iopub_channel.get_msg()
212 sub_msg = self.client.iopub_channel.get_msg()
214 msg_type = sub_msg['header']['msg_type']
213 msg_type = sub_msg['header']['msg_type']
215 parent = sub_msg["parent_header"]
214 parent = sub_msg["parent_header"]
216 if (not parent) or self.session_id == parent['session']:
215 if (not parent) or self.session_id == parent['session']:
217 if msg_type == 'status' :
216 if msg_type == 'status' :
218 if sub_msg["content"]["execution_state"] == "busy" :
217 if sub_msg["content"]["execution_state"] == "busy" :
219 pass
218 pass
220
219
221 elif msg_type == 'stream' :
220 elif msg_type == 'stream' :
222 if sub_msg["content"]["name"] == "stdout":
221 if sub_msg["content"]["name"] == "stdout":
223 print(sub_msg["content"]["data"], file=io.stdout, end="")
222 print(sub_msg["content"]["data"], file=io.stdout, end="")
224 io.stdout.flush()
223 io.stdout.flush()
225 elif sub_msg["content"]["name"] == "stderr" :
224 elif sub_msg["content"]["name"] == "stderr" :
226 print(sub_msg["content"]["data"], file=io.stderr, end="")
225 print(sub_msg["content"]["data"], file=io.stderr, end="")
227 io.stderr.flush()
226 io.stderr.flush()
228
227
229 elif msg_type == 'pyout':
228 elif msg_type == 'pyout':
230 self.execution_count = int(sub_msg["content"]["execution_count"])
229 self.execution_count = int(sub_msg["content"]["execution_count"])
231 format_dict = sub_msg["content"]["data"]
230 format_dict = sub_msg["content"]["data"]
232 self.handle_rich_data(format_dict)
231 self.handle_rich_data(format_dict)
233 # taken from DisplayHook.__call__:
232 # taken from DisplayHook.__call__:
234 hook = self.displayhook
233 hook = self.displayhook
235 hook.start_displayhook()
234 hook.start_displayhook()
236 hook.write_output_prompt()
235 hook.write_output_prompt()
237 hook.write_format_data(format_dict)
236 hook.write_format_data(format_dict)
238 hook.log_output(format_dict)
237 hook.log_output(format_dict)
239 hook.finish_displayhook()
238 hook.finish_displayhook()
240
239
241 elif msg_type == 'display_data':
240 elif msg_type == 'display_data':
242 self.handle_rich_data(sub_msg["content"]["data"])
241 self.handle_rich_data(sub_msg["content"]["data"])
243
242
244 _imagemime = {
243 _imagemime = {
245 'image/png': 'png',
244 'image/png': 'png',
246 'image/jpeg': 'jpeg',
245 'image/jpeg': 'jpeg',
247 'image/svg+xml': 'svg',
246 'image/svg+xml': 'svg',
248 }
247 }
249
248
250 def handle_rich_data(self, data):
249 def handle_rich_data(self, data):
251 for mime in self.mime_preference:
250 for mime in self.mime_preference:
252 if mime in data and mime in self._imagemime:
251 if mime in data and mime in self._imagemime:
253 self.handle_image(data, mime)
252 self.handle_image(data, mime)
254 return
253 return
255
254
256 def handle_image(self, data, mime):
255 def handle_image(self, data, mime):
257 handler = getattr(
256 handler = getattr(
258 self, 'handle_image_{0}'.format(self.image_handler), None)
257 self, 'handle_image_{0}'.format(self.image_handler), None)
259 if handler:
258 if handler:
260 handler(data, mime)
259 handler(data, mime)
261
260
262 def handle_image_PIL(self, data, mime):
261 def handle_image_PIL(self, data, mime):
263 if mime not in ('image/png', 'image/jpeg'):
262 if mime not in ('image/png', 'image/jpeg'):
264 return
263 return
265 import PIL.Image
264 import PIL.Image
266 raw = base64.decodestring(data[mime].encode('ascii'))
265 raw = base64.decodestring(data[mime].encode('ascii'))
267 img = PIL.Image.open(BytesIO(raw))
266 img = PIL.Image.open(BytesIO(raw))
268 img.show()
267 img.show()
269
268
270 def handle_image_stream(self, data, mime):
269 def handle_image_stream(self, data, mime):
271 raw = base64.decodestring(data[mime].encode('ascii'))
270 raw = base64.decodestring(data[mime].encode('ascii'))
272 imageformat = self._imagemime[mime]
271 imageformat = self._imagemime[mime]
273 fmt = dict(format=imageformat)
272 fmt = dict(format=imageformat)
274 args = [s.format(**fmt) for s in self.stream_image_handler]
273 args = [s.format(**fmt) for s in self.stream_image_handler]
275 with open(os.devnull, 'w') as devnull:
274 with open(os.devnull, 'w') as devnull:
276 proc = subprocess.Popen(
275 proc = subprocess.Popen(
277 args, stdin=subprocess.PIPE,
276 args, stdin=subprocess.PIPE,
278 stdout=devnull, stderr=devnull)
277 stdout=devnull, stderr=devnull)
279 proc.communicate(raw)
278 proc.communicate(raw)
280
279
281 def handle_image_tempfile(self, data, mime):
280 def handle_image_tempfile(self, data, mime):
282 raw = base64.decodestring(data[mime].encode('ascii'))
281 raw = base64.decodestring(data[mime].encode('ascii'))
283 imageformat = self._imagemime[mime]
282 imageformat = self._imagemime[mime]
284 filename = 'tmp.{0}'.format(imageformat)
283 filename = 'tmp.{0}'.format(imageformat)
285 with nested(NamedFileInTemporaryDirectory(filename),
284 with nested(NamedFileInTemporaryDirectory(filename),
286 open(os.devnull, 'w')) as (f, devnull):
285 open(os.devnull, 'w')) as (f, devnull):
287 f.write(raw)
286 f.write(raw)
288 f.flush()
287 f.flush()
289 fmt = dict(file=f.name, format=imageformat)
288 fmt = dict(file=f.name, format=imageformat)
290 args = [s.format(**fmt) for s in self.tempfile_image_handler]
289 args = [s.format(**fmt) for s in self.tempfile_image_handler]
291 subprocess.call(args, stdout=devnull, stderr=devnull)
290 subprocess.call(args, stdout=devnull, stderr=devnull)
292
291
293 def handle_image_callable(self, data, mime):
292 def handle_image_callable(self, data, mime):
294 self.callable_image_handler(data)
293 self.callable_image_handler(data)
295
294
296 def handle_stdin_request(self, timeout=0.1):
295 def handle_stdin_request(self, timeout=0.1):
297 """ Method to capture raw_input
296 """ Method to capture raw_input
298 """
297 """
299 msg_rep = self.client.stdin_channel.get_msg(timeout=timeout)
298 msg_rep = self.client.stdin_channel.get_msg(timeout=timeout)
300 # in case any iopub came while we were waiting:
299 # in case any iopub came while we were waiting:
301 self.handle_iopub()
300 self.handle_iopub()
302 if self.session_id == msg_rep["parent_header"].get("session"):
301 if self.session_id == msg_rep["parent_header"].get("session"):
303 # wrap SIGINT handler
302 # wrap SIGINT handler
304 real_handler = signal.getsignal(signal.SIGINT)
303 real_handler = signal.getsignal(signal.SIGINT)
305 def double_int(sig,frame):
304 def double_int(sig,frame):
306 # call real handler (forwards sigint to kernel),
305 # call real handler (forwards sigint to kernel),
307 # then raise local interrupt, stopping local raw_input
306 # then raise local interrupt, stopping local raw_input
308 real_handler(sig,frame)
307 real_handler(sig,frame)
309 raise KeyboardInterrupt
308 raise KeyboardInterrupt
310 signal.signal(signal.SIGINT, double_int)
309 signal.signal(signal.SIGINT, double_int)
311
310
312 try:
311 try:
313 raw_data = raw_input(msg_rep["content"]["prompt"])
312 raw_data = raw_input(msg_rep["content"]["prompt"])
314 except EOFError:
313 except EOFError:
315 # turn EOFError into EOF character
314 # turn EOFError into EOF character
316 raw_data = '\x04'
315 raw_data = '\x04'
317 except KeyboardInterrupt:
316 except KeyboardInterrupt:
318 sys.stdout.write('\n')
317 sys.stdout.write('\n')
319 return
318 return
320 finally:
319 finally:
321 # restore SIGINT handler
320 # restore SIGINT handler
322 signal.signal(signal.SIGINT, real_handler)
321 signal.signal(signal.SIGINT, real_handler)
323
322
324 # only send stdin reply if there *was not* another request
323 # only send stdin reply if there *was not* another request
325 # or execution finished while we were reading.
324 # or execution finished while we were reading.
326 if not (self.client.stdin_channel.msg_ready() or self.client.shell_channel.msg_ready()):
325 if not (self.client.stdin_channel.msg_ready() or self.client.shell_channel.msg_ready()):
327 self.client.stdin_channel.input(raw_data)
326 self.client.stdin_channel.input(raw_data)
328
327
329 def mainloop(self, display_banner=False):
328 def mainloop(self, display_banner=False):
330 while True:
329 while True:
331 try:
330 try:
332 self.interact(display_banner=display_banner)
331 self.interact(display_banner=display_banner)
333 #self.interact_with_readline()
332 #self.interact_with_readline()
334 # XXX for testing of a readline-decoupled repl loop, call
333 # XXX for testing of a readline-decoupled repl loop, call
335 # interact_with_readline above
334 # interact_with_readline above
336 break
335 break
337 except KeyboardInterrupt:
336 except KeyboardInterrupt:
338 # this should not be necessary, but KeyboardInterrupt
337 # this should not be necessary, but KeyboardInterrupt
339 # handling seems rather unpredictable...
338 # handling seems rather unpredictable...
340 self.write("\nKeyboardInterrupt in interact()\n")
339 self.write("\nKeyboardInterrupt in interact()\n")
341
340
342 def wait_for_kernel(self, timeout=None):
341 def wait_for_kernel(self, timeout=None):
343 """method to wait for a kernel to be ready"""
342 """method to wait for a kernel to be ready"""
344 tic = time.time()
343 tic = time.time()
345 self.client.hb_channel.unpause()
344 self.client.hb_channel.unpause()
346 while True:
345 while True:
347 self.run_cell('1', False)
346 self.run_cell('1', False)
348 if self.client.hb_channel.is_beating():
347 if self.client.hb_channel.is_beating():
349 # heart failure was not the reason this returned
348 # heart failure was not the reason this returned
350 break
349 break
351 else:
350 else:
352 # heart failed
351 # heart failed
353 if timeout is not None and (time.time() - tic) > timeout:
352 if timeout is not None and (time.time() - tic) > timeout:
354 return False
353 return False
355 return True
354 return True
356
355
357 def interact(self, display_banner=None):
356 def interact(self, display_banner=None):
358 """Closely emulate the interactive Python console."""
357 """Closely emulate the interactive Python console."""
359
358
360 # batch run -> do not interact
359 # batch run -> do not interact
361 if self.exit_now:
360 if self.exit_now:
362 return
361 return
363
362
364 if display_banner is None:
363 if display_banner is None:
365 display_banner = self.display_banner
364 display_banner = self.display_banner
366
365
367 if isinstance(display_banner, basestring):
366 if isinstance(display_banner, basestring):
368 self.show_banner(display_banner)
367 self.show_banner(display_banner)
369 elif display_banner:
368 elif display_banner:
370 self.show_banner()
369 self.show_banner()
371
370
372 more = False
371 more = False
373
372
374 # run a non-empty no-op, so that we don't get a prompt until
373 # run a non-empty no-op, so that we don't get a prompt until
375 # we know the kernel is ready. This keeps the connection
374 # we know the kernel is ready. This keeps the connection
376 # message above the first prompt.
375 # message above the first prompt.
377 if not self.wait_for_kernel(3):
376 if not self.wait_for_kernel(3):
378 error("Kernel did not respond\n")
377 error("Kernel did not respond\n")
379 return
378 return
380
379
381 if self.has_readline:
380 if self.has_readline:
382 self.readline_startup_hook(self.pre_readline)
381 self.readline_startup_hook(self.pre_readline)
383 hlen_b4_cell = self.readline.get_current_history_length()
382 hlen_b4_cell = self.readline.get_current_history_length()
384 else:
383 else:
385 hlen_b4_cell = 0
384 hlen_b4_cell = 0
386 # exit_now is set by a call to %Exit or %Quit, through the
385 # exit_now is set by a call to %Exit or %Quit, through the
387 # ask_exit callback.
386 # ask_exit callback.
388
387
389 while not self.exit_now:
388 while not self.exit_now:
390 if not self.client.is_alive():
389 if not self.client.is_alive():
391 # kernel died, prompt for action or exit
390 # kernel died, prompt for action or exit
392
391
393 action = "restart" if self.manager else "wait for restart"
392 action = "restart" if self.manager else "wait for restart"
394 ans = self.ask_yes_no("kernel died, %s ([y]/n)?" % action, default='y')
393 ans = self.ask_yes_no("kernel died, %s ([y]/n)?" % action, default='y')
395 if ans:
394 if ans:
396 if self.manager:
395 if self.manager:
397 self.manager.restart_kernel(True)
396 self.manager.restart_kernel(True)
398 self.wait_for_kernel(3)
397 self.wait_for_kernel(3)
399 else:
398 else:
400 self.exit_now = True
399 self.exit_now = True
401 continue
400 continue
402 try:
401 try:
403 # protect prompt block from KeyboardInterrupt
402 # protect prompt block from KeyboardInterrupt
404 # when sitting on ctrl-C
403 # when sitting on ctrl-C
405 self.hooks.pre_prompt_hook()
404 self.hooks.pre_prompt_hook()
406 if more:
405 if more:
407 try:
406 try:
408 prompt = self.prompt_manager.render('in2')
407 prompt = self.prompt_manager.render('in2')
409 except Exception:
408 except Exception:
410 self.showtraceback()
409 self.showtraceback()
411 if self.autoindent:
410 if self.autoindent:
412 self.rl_do_indent = True
411 self.rl_do_indent = True
413
412
414 else:
413 else:
415 try:
414 try:
416 prompt = self.separate_in + self.prompt_manager.render('in')
415 prompt = self.separate_in + self.prompt_manager.render('in')
417 except Exception:
416 except Exception:
418 self.showtraceback()
417 self.showtraceback()
419
418
420 line = self.raw_input(prompt)
419 line = self.raw_input(prompt)
421 if self.exit_now:
420 if self.exit_now:
422 # quick exit on sys.std[in|out] close
421 # quick exit on sys.std[in|out] close
423 break
422 break
424 if self.autoindent:
423 if self.autoindent:
425 self.rl_do_indent = False
424 self.rl_do_indent = False
426
425
427 except KeyboardInterrupt:
426 except KeyboardInterrupt:
428 #double-guard against keyboardinterrupts during kbdint handling
427 #double-guard against keyboardinterrupts during kbdint handling
429 try:
428 try:
430 self.write('\nKeyboardInterrupt\n')
429 self.write('\nKeyboardInterrupt\n')
431 source_raw = self.input_splitter.source_raw_reset()[1]
430 source_raw = self.input_splitter.source_raw_reset()[1]
432 hlen_b4_cell = self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
431 hlen_b4_cell = self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
433 more = False
432 more = False
434 except KeyboardInterrupt:
433 except KeyboardInterrupt:
435 pass
434 pass
436 except EOFError:
435 except EOFError:
437 if self.autoindent:
436 if self.autoindent:
438 self.rl_do_indent = False
437 self.rl_do_indent = False
439 if self.has_readline:
438 if self.has_readline:
440 self.readline_startup_hook(None)
439 self.readline_startup_hook(None)
441 self.write('\n')
440 self.write('\n')
442 self.exit()
441 self.exit()
443 except bdb.BdbQuit:
442 except bdb.BdbQuit:
444 warn('The Python debugger has exited with a BdbQuit exception.\n'
443 warn('The Python debugger has exited with a BdbQuit exception.\n'
445 'Because of how pdb handles the stack, it is impossible\n'
444 'Because of how pdb handles the stack, it is impossible\n'
446 'for IPython to properly format this particular exception.\n'
445 'for IPython to properly format this particular exception.\n'
447 'IPython will resume normal operation.')
446 'IPython will resume normal operation.')
448 except:
447 except:
449 # exceptions here are VERY RARE, but they can be triggered
448 # exceptions here are VERY RARE, but they can be triggered
450 # asynchronously by signal handlers, for example.
449 # asynchronously by signal handlers, for example.
451 self.showtraceback()
450 self.showtraceback()
452 else:
451 else:
453 self.input_splitter.push(line)
452 self.input_splitter.push(line)
454 more = self.input_splitter.push_accepts_more()
453 more = self.input_splitter.push_accepts_more()
455 if (self.SyntaxTB.last_syntax_error and
454 if (self.SyntaxTB.last_syntax_error and
456 self.autoedit_syntax):
455 self.autoedit_syntax):
457 self.edit_syntax_error()
456 self.edit_syntax_error()
458 if not more:
457 if not more:
459 source_raw = self.input_splitter.source_raw_reset()[1]
458 source_raw = self.input_splitter.source_raw_reset()[1]
460 hlen_b4_cell = self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
459 hlen_b4_cell = self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
461 self.run_cell(source_raw)
460 self.run_cell(source_raw)
462
461
463
462
464 # Turn off the exit flag, so the mainloop can be restarted if desired
463 # Turn off the exit flag, so the mainloop can be restarted if desired
465 self.exit_now = False
464 self.exit_now = False
@@ -1,59 +1,58 b''
1 """Tests for two-process terminal frontend
1 """Tests for two-process terminal frontend
2
2
3 Currenlty only has the most simple test possible, starting a console and running
3 Currenlty only has the most simple test possible, starting a console and running
4 a single command.
4 a single command.
5
5
6 Authors:
6 Authors:
7
7
8 * Min RK
8 * Min RK
9 """
9 """
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 import time
15 import time
16
16
17 import nose.tools as nt
17 import nose.tools as nt
18 from nose import SkipTest
18 from nose import SkipTest
19
19
20 from IPython.testing import decorators as dec
20 from IPython.testing import decorators as dec
21 from IPython.testing import tools as tt
22 from IPython.utils import py3compat
21 from IPython.utils import py3compat
23 from IPython.utils.process import find_cmd
22 from IPython.utils.process import find_cmd
24
23
25 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
26 # Test functions begin
25 # Test functions begin
27 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
28
27
29 @dec.skip_win32
28 @dec.skip_win32
30 def test_console_starts():
29 def test_console_starts():
31 """test that `ipython console` starts a terminal"""
30 """test that `ipython console` starts a terminal"""
32 from IPython.external import pexpect
31 from IPython.external import pexpect
33
32
34 # weird IOErrors prevent this from firing sometimes:
33 # weird IOErrors prevent this from firing sometimes:
35 ipython_cmd = None
34 ipython_cmd = None
36 for i in range(5):
35 for i in range(5):
37 try:
36 try:
38 ipython_cmd = find_cmd('ipython3' if py3compat.PY3 else 'ipython')
37 ipython_cmd = find_cmd('ipython3' if py3compat.PY3 else 'ipython')
39 except IOError:
38 except IOError:
40 time.sleep(0.1)
39 time.sleep(0.1)
41 else:
40 else:
42 break
41 break
43 if ipython_cmd is None:
42 if ipython_cmd is None:
44 raise SkipTest("Could not determine ipython command")
43 raise SkipTest("Could not determine ipython command")
45
44
46 p = pexpect.spawn(ipython_cmd, args=['console', '--colors=NoColor'])
45 p = pexpect.spawn(ipython_cmd, args=['console', '--colors=NoColor'])
47 idx = p.expect([r'In \[\d+\]', pexpect.EOF], timeout=15)
46 idx = p.expect([r'In \[\d+\]', pexpect.EOF], timeout=15)
48 nt.assert_equal(idx, 0, "expected in prompt")
47 nt.assert_equal(idx, 0, "expected in prompt")
49 p.sendline('5')
48 p.sendline('5')
50 idx = p.expect([r'Out\[\d+\]: 5', pexpect.EOF], timeout=5)
49 idx = p.expect([r'Out\[\d+\]: 5', pexpect.EOF], timeout=5)
51 nt.assert_equal(idx, 0, "expected out prompt")
50 nt.assert_equal(idx, 0, "expected out prompt")
52 idx = p.expect([r'In \[\d+\]', pexpect.EOF], timeout=5)
51 idx = p.expect([r'In \[\d+\]', pexpect.EOF], timeout=5)
53 nt.assert_equal(idx, 0, "expected second in prompt")
52 nt.assert_equal(idx, 0, "expected second in prompt")
54 # send ctrl-D;ctrl-D to exit
53 # send ctrl-D;ctrl-D to exit
55 p.sendeof()
54 p.sendeof()
56 p.sendeof()
55 p.sendeof()
57 p.expect([pexpect.EOF, pexpect.TIMEOUT], timeout=5)
56 p.expect([pexpect.EOF, pexpect.TIMEOUT], timeout=5)
58 if p.isalive():
57 if p.isalive():
59 p.terminate()
58 p.terminate()
@@ -1,696 +1,694 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Subclass of InteractiveShell for terminal based frontends."""
2 """Subclass of InteractiveShell for terminal based frontends."""
3
3
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
7 # Copyright (C) 2008-2011 The IPython Development Team
7 # Copyright (C) 2008-2011 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
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 import bdb
18 import bdb
19 import os
19 import os
20 import re
21 import sys
20 import sys
22 import textwrap
23
21
24 # We need to use nested to support python 2.6, once we move to >=2.7, we can
22 # We need to use nested to support python 2.6, once we move to >=2.7, we can
25 # use the with keyword's new builtin support for nested managers
23 # use the with keyword's new builtin support for nested managers
26 try:
24 try:
27 from contextlib import nested
25 from contextlib import nested
28 except:
26 except:
29 from IPython.utils.nested_context import nested
27 from IPython.utils.nested_context import nested
30
28
31 from IPython.core.error import TryNext, UsageError
29 from IPython.core.error import TryNext, UsageError
32 from IPython.core.usage import interactive_usage, default_banner
30 from IPython.core.usage import interactive_usage, default_banner
33 from IPython.core.inputsplitter import IPythonInputSplitter
31 from IPython.core.inputsplitter import IPythonInputSplitter
34 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
32 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
35 from IPython.core.magic import Magics, magics_class, line_magic
33 from IPython.core.magic import Magics, magics_class, line_magic
36 from IPython.testing.skipdoctest import skip_doctest
34 from IPython.testing.skipdoctest import skip_doctest
37 from IPython.utils.encoding import get_stream_enc
35 from IPython.utils.encoding import get_stream_enc
38 from IPython.utils import py3compat
36 from IPython.utils import py3compat
39 from IPython.utils.terminal import toggle_set_term_title, set_term_title
37 from IPython.utils.terminal import toggle_set_term_title, set_term_title
40 from IPython.utils.process import abbrev_cwd
38 from IPython.utils.process import abbrev_cwd
41 from IPython.utils.warn import warn, error
39 from IPython.utils.warn import warn, error
42 from IPython.utils.text import num_ini_spaces, SList, strip_email_quotes
40 from IPython.utils.text import num_ini_spaces, SList, strip_email_quotes
43 from IPython.utils.traitlets import Integer, CBool, Unicode
41 from IPython.utils.traitlets import Integer, CBool, Unicode
44
42
45 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
46 # Utilities
44 # Utilities
47 #-----------------------------------------------------------------------------
45 #-----------------------------------------------------------------------------
48
46
49 def get_default_editor():
47 def get_default_editor():
50 try:
48 try:
51 ed = os.environ['EDITOR']
49 ed = os.environ['EDITOR']
52 except KeyError:
50 except KeyError:
53 if os.name == 'posix':
51 if os.name == 'posix':
54 ed = 'vi' # the only one guaranteed to be there!
52 ed = 'vi' # the only one guaranteed to be there!
55 else:
53 else:
56 ed = 'notepad' # same in Windows!
54 ed = 'notepad' # same in Windows!
57 return ed
55 return ed
58
56
59
57
60 def get_pasted_lines(sentinel, l_input=py3compat.input):
58 def get_pasted_lines(sentinel, l_input=py3compat.input):
61 """ Yield pasted lines until the user enters the given sentinel value.
59 """ Yield pasted lines until the user enters the given sentinel value.
62 """
60 """
63 print("Pasting code; enter '%s' alone on the line to stop or use Ctrl-D." \
61 print("Pasting code; enter '%s' alone on the line to stop or use Ctrl-D." \
64 % sentinel)
62 % sentinel)
65 while True:
63 while True:
66 try:
64 try:
67 l = l_input(':')
65 l = l_input(':')
68 if l == sentinel:
66 if l == sentinel:
69 return
67 return
70 else:
68 else:
71 yield l
69 yield l
72 except EOFError:
70 except EOFError:
73 print('<EOF>')
71 print('<EOF>')
74 return
72 return
75
73
76
74
77 #------------------------------------------------------------------------
75 #------------------------------------------------------------------------
78 # Terminal-specific magics
76 # Terminal-specific magics
79 #------------------------------------------------------------------------
77 #------------------------------------------------------------------------
80
78
81 @magics_class
79 @magics_class
82 class TerminalMagics(Magics):
80 class TerminalMagics(Magics):
83 def __init__(self, shell):
81 def __init__(self, shell):
84 super(TerminalMagics, self).__init__(shell)
82 super(TerminalMagics, self).__init__(shell)
85 self.input_splitter = IPythonInputSplitter()
83 self.input_splitter = IPythonInputSplitter()
86
84
87 def store_or_execute(self, block, name):
85 def store_or_execute(self, block, name):
88 """ Execute a block, or store it in a variable, per the user's request.
86 """ Execute a block, or store it in a variable, per the user's request.
89 """
87 """
90 if name:
88 if name:
91 # If storing it for further editing
89 # If storing it for further editing
92 self.shell.user_ns[name] = SList(block.splitlines())
90 self.shell.user_ns[name] = SList(block.splitlines())
93 print("Block assigned to '%s'" % name)
91 print("Block assigned to '%s'" % name)
94 else:
92 else:
95 b = self.preclean_input(block)
93 b = self.preclean_input(block)
96 self.shell.user_ns['pasted_block'] = b
94 self.shell.user_ns['pasted_block'] = b
97 self.shell.using_paste_magics = True
95 self.shell.using_paste_magics = True
98 try:
96 try:
99 self.shell.run_cell(b)
97 self.shell.run_cell(b)
100 finally:
98 finally:
101 self.shell.using_paste_magics = False
99 self.shell.using_paste_magics = False
102
100
103 def preclean_input(self, block):
101 def preclean_input(self, block):
104 lines = block.splitlines()
102 lines = block.splitlines()
105 while lines and not lines[0].strip():
103 while lines and not lines[0].strip():
106 lines = lines[1:]
104 lines = lines[1:]
107 return strip_email_quotes('\n'.join(lines))
105 return strip_email_quotes('\n'.join(lines))
108
106
109 def rerun_pasted(self, name='pasted_block'):
107 def rerun_pasted(self, name='pasted_block'):
110 """ Rerun a previously pasted command.
108 """ Rerun a previously pasted command.
111 """
109 """
112 b = self.shell.user_ns.get(name)
110 b = self.shell.user_ns.get(name)
113
111
114 # Sanity checks
112 # Sanity checks
115 if b is None:
113 if b is None:
116 raise UsageError('No previous pasted block available')
114 raise UsageError('No previous pasted block available')
117 if not isinstance(b, basestring):
115 if not isinstance(b, basestring):
118 raise UsageError(
116 raise UsageError(
119 "Variable 'pasted_block' is not a string, can't execute")
117 "Variable 'pasted_block' is not a string, can't execute")
120
118
121 print("Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b)))
119 print("Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b)))
122 self.shell.run_cell(b)
120 self.shell.run_cell(b)
123
121
124 @line_magic
122 @line_magic
125 def autoindent(self, parameter_s = ''):
123 def autoindent(self, parameter_s = ''):
126 """Toggle autoindent on/off (if available)."""
124 """Toggle autoindent on/off (if available)."""
127
125
128 self.shell.set_autoindent()
126 self.shell.set_autoindent()
129 print("Automatic indentation is:",['OFF','ON'][self.shell.autoindent])
127 print("Automatic indentation is:",['OFF','ON'][self.shell.autoindent])
130
128
131 @skip_doctest
129 @skip_doctest
132 @line_magic
130 @line_magic
133 def cpaste(self, parameter_s=''):
131 def cpaste(self, parameter_s=''):
134 """Paste & execute a pre-formatted code block from clipboard.
132 """Paste & execute a pre-formatted code block from clipboard.
135
133
136 You must terminate the block with '--' (two minus-signs) or Ctrl-D
134 You must terminate the block with '--' (two minus-signs) or Ctrl-D
137 alone on the line. You can also provide your own sentinel with '%paste
135 alone on the line. You can also provide your own sentinel with '%paste
138 -s %%' ('%%' is the new sentinel for this operation)
136 -s %%' ('%%' is the new sentinel for this operation)
139
137
140 The block is dedented prior to execution to enable execution of method
138 The block is dedented prior to execution to enable execution of method
141 definitions. '>' and '+' characters at the beginning of a line are
139 definitions. '>' and '+' characters at the beginning of a line are
142 ignored, to allow pasting directly from e-mails, diff files and
140 ignored, to allow pasting directly from e-mails, diff files and
143 doctests (the '...' continuation prompt is also stripped). The
141 doctests (the '...' continuation prompt is also stripped). The
144 executed block is also assigned to variable named 'pasted_block' for
142 executed block is also assigned to variable named 'pasted_block' for
145 later editing with '%edit pasted_block'.
143 later editing with '%edit pasted_block'.
146
144
147 You can also pass a variable name as an argument, e.g. '%cpaste foo'.
145 You can also pass a variable name as an argument, e.g. '%cpaste foo'.
148 This assigns the pasted block to variable 'foo' as string, without
146 This assigns the pasted block to variable 'foo' as string, without
149 dedenting or executing it (preceding >>> and + is still stripped)
147 dedenting or executing it (preceding >>> and + is still stripped)
150
148
151 '%cpaste -r' re-executes the block previously entered by cpaste.
149 '%cpaste -r' re-executes the block previously entered by cpaste.
152
150
153 Do not be alarmed by garbled output on Windows (it's a readline bug).
151 Do not be alarmed by garbled output on Windows (it's a readline bug).
154 Just press enter and type -- (and press enter again) and the block
152 Just press enter and type -- (and press enter again) and the block
155 will be what was just pasted.
153 will be what was just pasted.
156
154
157 IPython statements (magics, shell escapes) are not supported (yet).
155 IPython statements (magics, shell escapes) are not supported (yet).
158
156
159 See also
157 See also
160 --------
158 --------
161 paste: automatically pull code from clipboard.
159 paste: automatically pull code from clipboard.
162
160
163 Examples
161 Examples
164 --------
162 --------
165 ::
163 ::
166
164
167 In [8]: %cpaste
165 In [8]: %cpaste
168 Pasting code; enter '--' alone on the line to stop.
166 Pasting code; enter '--' alone on the line to stop.
169 :>>> a = ["world!", "Hello"]
167 :>>> a = ["world!", "Hello"]
170 :>>> print " ".join(sorted(a))
168 :>>> print " ".join(sorted(a))
171 :--
169 :--
172 Hello world!
170 Hello world!
173 """
171 """
174 opts, name = self.parse_options(parameter_s, 'rs:', mode='string')
172 opts, name = self.parse_options(parameter_s, 'rs:', mode='string')
175 if 'r' in opts:
173 if 'r' in opts:
176 self.rerun_pasted()
174 self.rerun_pasted()
177 return
175 return
178
176
179 sentinel = opts.get('s', '--')
177 sentinel = opts.get('s', '--')
180 block = '\n'.join(get_pasted_lines(sentinel))
178 block = '\n'.join(get_pasted_lines(sentinel))
181 self.store_or_execute(block, name)
179 self.store_or_execute(block, name)
182
180
183 @line_magic
181 @line_magic
184 def paste(self, parameter_s=''):
182 def paste(self, parameter_s=''):
185 """Paste & execute a pre-formatted code block from clipboard.
183 """Paste & execute a pre-formatted code block from clipboard.
186
184
187 The text is pulled directly from the clipboard without user
185 The text is pulled directly from the clipboard without user
188 intervention and printed back on the screen before execution (unless
186 intervention and printed back on the screen before execution (unless
189 the -q flag is given to force quiet mode).
187 the -q flag is given to force quiet mode).
190
188
191 The block is dedented prior to execution to enable execution of method
189 The block is dedented prior to execution to enable execution of method
192 definitions. '>' and '+' characters at the beginning of a line are
190 definitions. '>' and '+' characters at the beginning of a line are
193 ignored, to allow pasting directly from e-mails, diff files and
191 ignored, to allow pasting directly from e-mails, diff files and
194 doctests (the '...' continuation prompt is also stripped). The
192 doctests (the '...' continuation prompt is also stripped). The
195 executed block is also assigned to variable named 'pasted_block' for
193 executed block is also assigned to variable named 'pasted_block' for
196 later editing with '%edit pasted_block'.
194 later editing with '%edit pasted_block'.
197
195
198 You can also pass a variable name as an argument, e.g. '%paste foo'.
196 You can also pass a variable name as an argument, e.g. '%paste foo'.
199 This assigns the pasted block to variable 'foo' as string, without
197 This assigns the pasted block to variable 'foo' as string, without
200 executing it (preceding >>> and + is still stripped).
198 executing it (preceding >>> and + is still stripped).
201
199
202 Options
200 Options
203 -------
201 -------
204
202
205 -r: re-executes the block previously entered by cpaste.
203 -r: re-executes the block previously entered by cpaste.
206
204
207 -q: quiet mode: do not echo the pasted text back to the terminal.
205 -q: quiet mode: do not echo the pasted text back to the terminal.
208
206
209 IPython statements (magics, shell escapes) are not supported (yet).
207 IPython statements (magics, shell escapes) are not supported (yet).
210
208
211 See also
209 See also
212 --------
210 --------
213 cpaste: manually paste code into terminal until you mark its end.
211 cpaste: manually paste code into terminal until you mark its end.
214 """
212 """
215 opts, name = self.parse_options(parameter_s, 'rq', mode='string')
213 opts, name = self.parse_options(parameter_s, 'rq', mode='string')
216 if 'r' in opts:
214 if 'r' in opts:
217 self.rerun_pasted()
215 self.rerun_pasted()
218 return
216 return
219 try:
217 try:
220 block = self.shell.hooks.clipboard_get()
218 block = self.shell.hooks.clipboard_get()
221 except TryNext as clipboard_exc:
219 except TryNext as clipboard_exc:
222 message = getattr(clipboard_exc, 'args')
220 message = getattr(clipboard_exc, 'args')
223 if message:
221 if message:
224 error(message[0])
222 error(message[0])
225 else:
223 else:
226 error('Could not get text from the clipboard.')
224 error('Could not get text from the clipboard.')
227 return
225 return
228
226
229 # By default, echo back to terminal unless quiet mode is requested
227 # By default, echo back to terminal unless quiet mode is requested
230 if 'q' not in opts:
228 if 'q' not in opts:
231 write = self.shell.write
229 write = self.shell.write
232 write(self.shell.pycolorize(block))
230 write(self.shell.pycolorize(block))
233 if not block.endswith('\n'):
231 if not block.endswith('\n'):
234 write('\n')
232 write('\n')
235 write("## -- End pasted text --\n")
233 write("## -- End pasted text --\n")
236
234
237 self.store_or_execute(block, name)
235 self.store_or_execute(block, name)
238
236
239 # Class-level: add a '%cls' magic only on Windows
237 # Class-level: add a '%cls' magic only on Windows
240 if sys.platform == 'win32':
238 if sys.platform == 'win32':
241 @line_magic
239 @line_magic
242 def cls(self, s):
240 def cls(self, s):
243 """Clear screen.
241 """Clear screen.
244 """
242 """
245 os.system("cls")
243 os.system("cls")
246
244
247 #-----------------------------------------------------------------------------
245 #-----------------------------------------------------------------------------
248 # Main class
246 # Main class
249 #-----------------------------------------------------------------------------
247 #-----------------------------------------------------------------------------
250
248
251 class TerminalInteractiveShell(InteractiveShell):
249 class TerminalInteractiveShell(InteractiveShell):
252
250
253 autoedit_syntax = CBool(False, config=True,
251 autoedit_syntax = CBool(False, config=True,
254 help="auto editing of files with syntax errors.")
252 help="auto editing of files with syntax errors.")
255 banner = Unicode('')
253 banner = Unicode('')
256 banner1 = Unicode(default_banner, config=True,
254 banner1 = Unicode(default_banner, config=True,
257 help="""The part of the banner to be printed before the profile"""
255 help="""The part of the banner to be printed before the profile"""
258 )
256 )
259 banner2 = Unicode('', config=True,
257 banner2 = Unicode('', config=True,
260 help="""The part of the banner to be printed after the profile"""
258 help="""The part of the banner to be printed after the profile"""
261 )
259 )
262 confirm_exit = CBool(True, config=True,
260 confirm_exit = CBool(True, config=True,
263 help="""
261 help="""
264 Set to confirm when you try to exit IPython with an EOF (Control-D
262 Set to confirm when you try to exit IPython with an EOF (Control-D
265 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
263 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
266 you can force a direct exit without any confirmation.""",
264 you can force a direct exit without any confirmation.""",
267 )
265 )
268 # This display_banner only controls whether or not self.show_banner()
266 # This display_banner only controls whether or not self.show_banner()
269 # is called when mainloop/interact are called. The default is False
267 # is called when mainloop/interact are called. The default is False
270 # because for the terminal based application, the banner behavior
268 # because for the terminal based application, the banner behavior
271 # is controlled by Global.display_banner, which IPythonApp looks at
269 # is controlled by Global.display_banner, which IPythonApp looks at
272 # to determine if *it* should call show_banner() by hand or not.
270 # to determine if *it* should call show_banner() by hand or not.
273 display_banner = CBool(False) # This isn't configurable!
271 display_banner = CBool(False) # This isn't configurable!
274 embedded = CBool(False)
272 embedded = CBool(False)
275 embedded_active = CBool(False)
273 embedded_active = CBool(False)
276 editor = Unicode(get_default_editor(), config=True,
274 editor = Unicode(get_default_editor(), config=True,
277 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
275 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
278 )
276 )
279 pager = Unicode('less', config=True,
277 pager = Unicode('less', config=True,
280 help="The shell program to be used for paging.")
278 help="The shell program to be used for paging.")
281
279
282 screen_length = Integer(0, config=True,
280 screen_length = Integer(0, config=True,
283 help=
281 help=
284 """Number of lines of your screen, used to control printing of very
282 """Number of lines of your screen, used to control printing of very
285 long strings. Strings longer than this number of lines will be sent
283 long strings. Strings longer than this number of lines will be sent
286 through a pager instead of directly printed. The default value for
284 through a pager instead of directly printed. The default value for
287 this is 0, which means IPython will auto-detect your screen size every
285 this is 0, which means IPython will auto-detect your screen size every
288 time it needs to print certain potentially long strings (this doesn't
286 time it needs to print certain potentially long strings (this doesn't
289 change the behavior of the 'print' keyword, it's only triggered
287 change the behavior of the 'print' keyword, it's only triggered
290 internally). If for some reason this isn't working well (it needs
288 internally). If for some reason this isn't working well (it needs
291 curses support), specify it yourself. Otherwise don't change the
289 curses support), specify it yourself. Otherwise don't change the
292 default.""",
290 default.""",
293 )
291 )
294 term_title = CBool(False, config=True,
292 term_title = CBool(False, config=True,
295 help="Enable auto setting the terminal title."
293 help="Enable auto setting the terminal title."
296 )
294 )
297
295
298 # This `using_paste_magics` is used to detect whether the code is being
296 # This `using_paste_magics` is used to detect whether the code is being
299 # executed via paste magics functions
297 # executed via paste magics functions
300 using_paste_magics = CBool(False)
298 using_paste_magics = CBool(False)
301
299
302 # In the terminal, GUI control is done via PyOS_InputHook
300 # In the terminal, GUI control is done via PyOS_InputHook
303 @staticmethod
301 @staticmethod
304 def enable_gui(gui=None, app=None):
302 def enable_gui(gui=None, app=None):
305 """Switch amongst GUI input hooks by name.
303 """Switch amongst GUI input hooks by name.
306 """
304 """
307 # Deferred import
305 # Deferred import
308 from IPython.lib.inputhook import enable_gui as real_enable_gui
306 from IPython.lib.inputhook import enable_gui as real_enable_gui
309 return real_enable_gui(gui, app)
307 return real_enable_gui(gui, app)
310
308
311 def __init__(self, config=None, ipython_dir=None, profile_dir=None,
309 def __init__(self, config=None, ipython_dir=None, profile_dir=None,
312 user_ns=None, user_module=None, custom_exceptions=((),None),
310 user_ns=None, user_module=None, custom_exceptions=((),None),
313 usage=None, banner1=None, banner2=None, display_banner=None,
311 usage=None, banner1=None, banner2=None, display_banner=None,
314 **kwargs):
312 **kwargs):
315
313
316 super(TerminalInteractiveShell, self).__init__(
314 super(TerminalInteractiveShell, self).__init__(
317 config=config, ipython_dir=ipython_dir, profile_dir=profile_dir, user_ns=user_ns,
315 config=config, ipython_dir=ipython_dir, profile_dir=profile_dir, user_ns=user_ns,
318 user_module=user_module, custom_exceptions=custom_exceptions,
316 user_module=user_module, custom_exceptions=custom_exceptions,
319 **kwargs
317 **kwargs
320 )
318 )
321 # use os.system instead of utils.process.system by default,
319 # use os.system instead of utils.process.system by default,
322 # because piped system doesn't make sense in the Terminal:
320 # because piped system doesn't make sense in the Terminal:
323 self.system = self.system_raw
321 self.system = self.system_raw
324
322
325 self.init_term_title()
323 self.init_term_title()
326 self.init_usage(usage)
324 self.init_usage(usage)
327 self.init_banner(banner1, banner2, display_banner)
325 self.init_banner(banner1, banner2, display_banner)
328
326
329 #-------------------------------------------------------------------------
327 #-------------------------------------------------------------------------
330 # Overrides of init stages
328 # Overrides of init stages
331 #-------------------------------------------------------------------------
329 #-------------------------------------------------------------------------
332
330
333 def init_display_formatter(self):
331 def init_display_formatter(self):
334 super(TerminalInteractiveShell, self).init_display_formatter()
332 super(TerminalInteractiveShell, self).init_display_formatter()
335 # terminal only supports plaintext
333 # terminal only supports plaintext
336 self.display_formatter.active_types = ['text/plain']
334 self.display_formatter.active_types = ['text/plain']
337
335
338 #-------------------------------------------------------------------------
336 #-------------------------------------------------------------------------
339 # Things related to the terminal
337 # Things related to the terminal
340 #-------------------------------------------------------------------------
338 #-------------------------------------------------------------------------
341
339
342 @property
340 @property
343 def usable_screen_length(self):
341 def usable_screen_length(self):
344 if self.screen_length == 0:
342 if self.screen_length == 0:
345 return 0
343 return 0
346 else:
344 else:
347 num_lines_bot = self.separate_in.count('\n')+1
345 num_lines_bot = self.separate_in.count('\n')+1
348 return self.screen_length - num_lines_bot
346 return self.screen_length - num_lines_bot
349
347
350 def init_term_title(self):
348 def init_term_title(self):
351 # Enable or disable the terminal title.
349 # Enable or disable the terminal title.
352 if self.term_title:
350 if self.term_title:
353 toggle_set_term_title(True)
351 toggle_set_term_title(True)
354 set_term_title('IPython: ' + abbrev_cwd())
352 set_term_title('IPython: ' + abbrev_cwd())
355 else:
353 else:
356 toggle_set_term_title(False)
354 toggle_set_term_title(False)
357
355
358 #-------------------------------------------------------------------------
356 #-------------------------------------------------------------------------
359 # Things related to aliases
357 # Things related to aliases
360 #-------------------------------------------------------------------------
358 #-------------------------------------------------------------------------
361
359
362 def init_alias(self):
360 def init_alias(self):
363 # The parent class defines aliases that can be safely used with any
361 # The parent class defines aliases that can be safely used with any
364 # frontend.
362 # frontend.
365 super(TerminalInteractiveShell, self).init_alias()
363 super(TerminalInteractiveShell, self).init_alias()
366
364
367 # Now define aliases that only make sense on the terminal, because they
365 # Now define aliases that only make sense on the terminal, because they
368 # need direct access to the console in a way that we can't emulate in
366 # need direct access to the console in a way that we can't emulate in
369 # GUI or web frontend
367 # GUI or web frontend
370 if os.name == 'posix':
368 if os.name == 'posix':
371 aliases = [('clear', 'clear'), ('more', 'more'), ('less', 'less'),
369 aliases = [('clear', 'clear'), ('more', 'more'), ('less', 'less'),
372 ('man', 'man')]
370 ('man', 'man')]
373 elif os.name == 'nt':
371 elif os.name == 'nt':
374 aliases = [('cls', 'cls')]
372 aliases = [('cls', 'cls')]
375
373
376
374
377 for name, cmd in aliases:
375 for name, cmd in aliases:
378 self.alias_manager.define_alias(name, cmd)
376 self.alias_manager.define_alias(name, cmd)
379
377
380 #-------------------------------------------------------------------------
378 #-------------------------------------------------------------------------
381 # Things related to the banner and usage
379 # Things related to the banner and usage
382 #-------------------------------------------------------------------------
380 #-------------------------------------------------------------------------
383
381
384 def _banner1_changed(self):
382 def _banner1_changed(self):
385 self.compute_banner()
383 self.compute_banner()
386
384
387 def _banner2_changed(self):
385 def _banner2_changed(self):
388 self.compute_banner()
386 self.compute_banner()
389
387
390 def _term_title_changed(self, name, new_value):
388 def _term_title_changed(self, name, new_value):
391 self.init_term_title()
389 self.init_term_title()
392
390
393 def init_banner(self, banner1, banner2, display_banner):
391 def init_banner(self, banner1, banner2, display_banner):
394 if banner1 is not None:
392 if banner1 is not None:
395 self.banner1 = banner1
393 self.banner1 = banner1
396 if banner2 is not None:
394 if banner2 is not None:
397 self.banner2 = banner2
395 self.banner2 = banner2
398 if display_banner is not None:
396 if display_banner is not None:
399 self.display_banner = display_banner
397 self.display_banner = display_banner
400 self.compute_banner()
398 self.compute_banner()
401
399
402 def show_banner(self, banner=None):
400 def show_banner(self, banner=None):
403 if banner is None:
401 if banner is None:
404 banner = self.banner
402 banner = self.banner
405 self.write(banner)
403 self.write(banner)
406
404
407 def compute_banner(self):
405 def compute_banner(self):
408 self.banner = self.banner1
406 self.banner = self.banner1
409 if self.profile and self.profile != 'default':
407 if self.profile and self.profile != 'default':
410 self.banner += '\nIPython profile: %s\n' % self.profile
408 self.banner += '\nIPython profile: %s\n' % self.profile
411 if self.banner2:
409 if self.banner2:
412 self.banner += '\n' + self.banner2
410 self.banner += '\n' + self.banner2
413
411
414 def init_usage(self, usage=None):
412 def init_usage(self, usage=None):
415 if usage is None:
413 if usage is None:
416 self.usage = interactive_usage
414 self.usage = interactive_usage
417 else:
415 else:
418 self.usage = usage
416 self.usage = usage
419
417
420 #-------------------------------------------------------------------------
418 #-------------------------------------------------------------------------
421 # Mainloop and code execution logic
419 # Mainloop and code execution logic
422 #-------------------------------------------------------------------------
420 #-------------------------------------------------------------------------
423
421
424 def mainloop(self, display_banner=None):
422 def mainloop(self, display_banner=None):
425 """Start the mainloop.
423 """Start the mainloop.
426
424
427 If an optional banner argument is given, it will override the
425 If an optional banner argument is given, it will override the
428 internally created default banner.
426 internally created default banner.
429 """
427 """
430
428
431 with nested(self.builtin_trap, self.display_trap):
429 with nested(self.builtin_trap, self.display_trap):
432
430
433 while 1:
431 while 1:
434 try:
432 try:
435 self.interact(display_banner=display_banner)
433 self.interact(display_banner=display_banner)
436 #self.interact_with_readline()
434 #self.interact_with_readline()
437 # XXX for testing of a readline-decoupled repl loop, call
435 # XXX for testing of a readline-decoupled repl loop, call
438 # interact_with_readline above
436 # interact_with_readline above
439 break
437 break
440 except KeyboardInterrupt:
438 except KeyboardInterrupt:
441 # this should not be necessary, but KeyboardInterrupt
439 # this should not be necessary, but KeyboardInterrupt
442 # handling seems rather unpredictable...
440 # handling seems rather unpredictable...
443 self.write("\nKeyboardInterrupt in interact()\n")
441 self.write("\nKeyboardInterrupt in interact()\n")
444
442
445 def _replace_rlhist_multiline(self, source_raw, hlen_before_cell):
443 def _replace_rlhist_multiline(self, source_raw, hlen_before_cell):
446 """Store multiple lines as a single entry in history"""
444 """Store multiple lines as a single entry in history"""
447
445
448 # do nothing without readline or disabled multiline
446 # do nothing without readline or disabled multiline
449 if not self.has_readline or not self.multiline_history:
447 if not self.has_readline or not self.multiline_history:
450 return hlen_before_cell
448 return hlen_before_cell
451
449
452 # windows rl has no remove_history_item
450 # windows rl has no remove_history_item
453 if not hasattr(self.readline, "remove_history_item"):
451 if not hasattr(self.readline, "remove_history_item"):
454 return hlen_before_cell
452 return hlen_before_cell
455
453
456 # skip empty cells
454 # skip empty cells
457 if not source_raw.rstrip():
455 if not source_raw.rstrip():
458 return hlen_before_cell
456 return hlen_before_cell
459
457
460 # nothing changed do nothing, e.g. when rl removes consecutive dups
458 # nothing changed do nothing, e.g. when rl removes consecutive dups
461 hlen = self.readline.get_current_history_length()
459 hlen = self.readline.get_current_history_length()
462 if hlen == hlen_before_cell:
460 if hlen == hlen_before_cell:
463 return hlen_before_cell
461 return hlen_before_cell
464
462
465 for i in range(hlen - hlen_before_cell):
463 for i in range(hlen - hlen_before_cell):
466 self.readline.remove_history_item(hlen - i - 1)
464 self.readline.remove_history_item(hlen - i - 1)
467 stdin_encoding = get_stream_enc(sys.stdin, 'utf-8')
465 stdin_encoding = get_stream_enc(sys.stdin, 'utf-8')
468 self.readline.add_history(py3compat.unicode_to_str(source_raw.rstrip(),
466 self.readline.add_history(py3compat.unicode_to_str(source_raw.rstrip(),
469 stdin_encoding))
467 stdin_encoding))
470 return self.readline.get_current_history_length()
468 return self.readline.get_current_history_length()
471
469
472 def interact(self, display_banner=None):
470 def interact(self, display_banner=None):
473 """Closely emulate the interactive Python console."""
471 """Closely emulate the interactive Python console."""
474
472
475 # batch run -> do not interact
473 # batch run -> do not interact
476 if self.exit_now:
474 if self.exit_now:
477 return
475 return
478
476
479 if display_banner is None:
477 if display_banner is None:
480 display_banner = self.display_banner
478 display_banner = self.display_banner
481
479
482 if isinstance(display_banner, basestring):
480 if isinstance(display_banner, basestring):
483 self.show_banner(display_banner)
481 self.show_banner(display_banner)
484 elif display_banner:
482 elif display_banner:
485 self.show_banner()
483 self.show_banner()
486
484
487 more = False
485 more = False
488
486
489 if self.has_readline:
487 if self.has_readline:
490 self.readline_startup_hook(self.pre_readline)
488 self.readline_startup_hook(self.pre_readline)
491 hlen_b4_cell = self.readline.get_current_history_length()
489 hlen_b4_cell = self.readline.get_current_history_length()
492 else:
490 else:
493 hlen_b4_cell = 0
491 hlen_b4_cell = 0
494 # exit_now is set by a call to %Exit or %Quit, through the
492 # exit_now is set by a call to %Exit or %Quit, through the
495 # ask_exit callback.
493 # ask_exit callback.
496
494
497 while not self.exit_now:
495 while not self.exit_now:
498 self.hooks.pre_prompt_hook()
496 self.hooks.pre_prompt_hook()
499 if more:
497 if more:
500 try:
498 try:
501 prompt = self.prompt_manager.render('in2')
499 prompt = self.prompt_manager.render('in2')
502 except:
500 except:
503 self.showtraceback()
501 self.showtraceback()
504 if self.autoindent:
502 if self.autoindent:
505 self.rl_do_indent = True
503 self.rl_do_indent = True
506
504
507 else:
505 else:
508 try:
506 try:
509 prompt = self.separate_in + self.prompt_manager.render('in')
507 prompt = self.separate_in + self.prompt_manager.render('in')
510 except:
508 except:
511 self.showtraceback()
509 self.showtraceback()
512 try:
510 try:
513 line = self.raw_input(prompt)
511 line = self.raw_input(prompt)
514 if self.exit_now:
512 if self.exit_now:
515 # quick exit on sys.std[in|out] close
513 # quick exit on sys.std[in|out] close
516 break
514 break
517 if self.autoindent:
515 if self.autoindent:
518 self.rl_do_indent = False
516 self.rl_do_indent = False
519
517
520 except KeyboardInterrupt:
518 except KeyboardInterrupt:
521 #double-guard against keyboardinterrupts during kbdint handling
519 #double-guard against keyboardinterrupts during kbdint handling
522 try:
520 try:
523 self.write('\nKeyboardInterrupt\n')
521 self.write('\nKeyboardInterrupt\n')
524 source_raw = self.input_splitter.source_raw_reset()[1]
522 source_raw = self.input_splitter.source_raw_reset()[1]
525 hlen_b4_cell = \
523 hlen_b4_cell = \
526 self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
524 self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
527 more = False
525 more = False
528 except KeyboardInterrupt:
526 except KeyboardInterrupt:
529 pass
527 pass
530 except EOFError:
528 except EOFError:
531 if self.autoindent:
529 if self.autoindent:
532 self.rl_do_indent = False
530 self.rl_do_indent = False
533 if self.has_readline:
531 if self.has_readline:
534 self.readline_startup_hook(None)
532 self.readline_startup_hook(None)
535 self.write('\n')
533 self.write('\n')
536 self.exit()
534 self.exit()
537 except bdb.BdbQuit:
535 except bdb.BdbQuit:
538 warn('The Python debugger has exited with a BdbQuit exception.\n'
536 warn('The Python debugger has exited with a BdbQuit exception.\n'
539 'Because of how pdb handles the stack, it is impossible\n'
537 'Because of how pdb handles the stack, it is impossible\n'
540 'for IPython to properly format this particular exception.\n'
538 'for IPython to properly format this particular exception.\n'
541 'IPython will resume normal operation.')
539 'IPython will resume normal operation.')
542 except:
540 except:
543 # exceptions here are VERY RARE, but they can be triggered
541 # exceptions here are VERY RARE, but they can be triggered
544 # asynchronously by signal handlers, for example.
542 # asynchronously by signal handlers, for example.
545 self.showtraceback()
543 self.showtraceback()
546 else:
544 else:
547 self.input_splitter.push(line)
545 self.input_splitter.push(line)
548 more = self.input_splitter.push_accepts_more()
546 more = self.input_splitter.push_accepts_more()
549 if (self.SyntaxTB.last_syntax_error and
547 if (self.SyntaxTB.last_syntax_error and
550 self.autoedit_syntax):
548 self.autoedit_syntax):
551 self.edit_syntax_error()
549 self.edit_syntax_error()
552 if not more:
550 if not more:
553 source_raw = self.input_splitter.source_raw_reset()[1]
551 source_raw = self.input_splitter.source_raw_reset()[1]
554 self.run_cell(source_raw, store_history=True)
552 self.run_cell(source_raw, store_history=True)
555 hlen_b4_cell = \
553 hlen_b4_cell = \
556 self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
554 self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
557
555
558 # Turn off the exit flag, so the mainloop can be restarted if desired
556 # Turn off the exit flag, so the mainloop can be restarted if desired
559 self.exit_now = False
557 self.exit_now = False
560
558
561 def raw_input(self, prompt=''):
559 def raw_input(self, prompt=''):
562 """Write a prompt and read a line.
560 """Write a prompt and read a line.
563
561
564 The returned line does not include the trailing newline.
562 The returned line does not include the trailing newline.
565 When the user enters the EOF key sequence, EOFError is raised.
563 When the user enters the EOF key sequence, EOFError is raised.
566
564
567 Optional inputs:
565 Optional inputs:
568
566
569 - prompt(''): a string to be printed to prompt the user.
567 - prompt(''): a string to be printed to prompt the user.
570
568
571 - continue_prompt(False): whether this line is the first one or a
569 - continue_prompt(False): whether this line is the first one or a
572 continuation in a sequence of inputs.
570 continuation in a sequence of inputs.
573 """
571 """
574 # Code run by the user may have modified the readline completer state.
572 # Code run by the user may have modified the readline completer state.
575 # We must ensure that our completer is back in place.
573 # We must ensure that our completer is back in place.
576
574
577 if self.has_readline:
575 if self.has_readline:
578 self.set_readline_completer()
576 self.set_readline_completer()
579
577
580 # raw_input expects str, but we pass it unicode sometimes
578 # raw_input expects str, but we pass it unicode sometimes
581 prompt = py3compat.cast_bytes_py2(prompt)
579 prompt = py3compat.cast_bytes_py2(prompt)
582
580
583 try:
581 try:
584 line = py3compat.str_to_unicode(self.raw_input_original(prompt))
582 line = py3compat.str_to_unicode(self.raw_input_original(prompt))
585 except ValueError:
583 except ValueError:
586 warn("\n********\nYou or a %run:ed script called sys.stdin.close()"
584 warn("\n********\nYou or a %run:ed script called sys.stdin.close()"
587 " or sys.stdout.close()!\nExiting IPython!\n")
585 " or sys.stdout.close()!\nExiting IPython!\n")
588 self.ask_exit()
586 self.ask_exit()
589 return ""
587 return ""
590
588
591 # Try to be reasonably smart about not re-indenting pasted input more
589 # Try to be reasonably smart about not re-indenting pasted input more
592 # than necessary. We do this by trimming out the auto-indent initial
590 # than necessary. We do this by trimming out the auto-indent initial
593 # spaces, if the user's actual input started itself with whitespace.
591 # spaces, if the user's actual input started itself with whitespace.
594 if self.autoindent:
592 if self.autoindent:
595 if num_ini_spaces(line) > self.indent_current_nsp:
593 if num_ini_spaces(line) > self.indent_current_nsp:
596 line = line[self.indent_current_nsp:]
594 line = line[self.indent_current_nsp:]
597 self.indent_current_nsp = 0
595 self.indent_current_nsp = 0
598
596
599 return line
597 return line
600
598
601 #-------------------------------------------------------------------------
599 #-------------------------------------------------------------------------
602 # Methods to support auto-editing of SyntaxErrors.
600 # Methods to support auto-editing of SyntaxErrors.
603 #-------------------------------------------------------------------------
601 #-------------------------------------------------------------------------
604
602
605 def edit_syntax_error(self):
603 def edit_syntax_error(self):
606 """The bottom half of the syntax error handler called in the main loop.
604 """The bottom half of the syntax error handler called in the main loop.
607
605
608 Loop until syntax error is fixed or user cancels.
606 Loop until syntax error is fixed or user cancels.
609 """
607 """
610
608
611 while self.SyntaxTB.last_syntax_error:
609 while self.SyntaxTB.last_syntax_error:
612 # copy and clear last_syntax_error
610 # copy and clear last_syntax_error
613 err = self.SyntaxTB.clear_err_state()
611 err = self.SyntaxTB.clear_err_state()
614 if not self._should_recompile(err):
612 if not self._should_recompile(err):
615 return
613 return
616 try:
614 try:
617 # may set last_syntax_error again if a SyntaxError is raised
615 # may set last_syntax_error again if a SyntaxError is raised
618 self.safe_execfile(err.filename,self.user_ns)
616 self.safe_execfile(err.filename,self.user_ns)
619 except:
617 except:
620 self.showtraceback()
618 self.showtraceback()
621 else:
619 else:
622 try:
620 try:
623 f = open(err.filename)
621 f = open(err.filename)
624 try:
622 try:
625 # This should be inside a display_trap block and I
623 # This should be inside a display_trap block and I
626 # think it is.
624 # think it is.
627 sys.displayhook(f.read())
625 sys.displayhook(f.read())
628 finally:
626 finally:
629 f.close()
627 f.close()
630 except:
628 except:
631 self.showtraceback()
629 self.showtraceback()
632
630
633 def _should_recompile(self,e):
631 def _should_recompile(self,e):
634 """Utility routine for edit_syntax_error"""
632 """Utility routine for edit_syntax_error"""
635
633
636 if e.filename in ('<ipython console>','<input>','<string>',
634 if e.filename in ('<ipython console>','<input>','<string>',
637 '<console>','<BackgroundJob compilation>',
635 '<console>','<BackgroundJob compilation>',
638 None):
636 None):
639
637
640 return False
638 return False
641 try:
639 try:
642 if (self.autoedit_syntax and
640 if (self.autoedit_syntax and
643 not self.ask_yes_no('Return to editor to correct syntax error? '
641 not self.ask_yes_no('Return to editor to correct syntax error? '
644 '[Y/n] ','y')):
642 '[Y/n] ','y')):
645 return False
643 return False
646 except EOFError:
644 except EOFError:
647 return False
645 return False
648
646
649 def int0(x):
647 def int0(x):
650 try:
648 try:
651 return int(x)
649 return int(x)
652 except TypeError:
650 except TypeError:
653 return 0
651 return 0
654 # always pass integer line and offset values to editor hook
652 # always pass integer line and offset values to editor hook
655 try:
653 try:
656 self.hooks.fix_error_editor(e.filename,
654 self.hooks.fix_error_editor(e.filename,
657 int0(e.lineno),int0(e.offset),e.msg)
655 int0(e.lineno),int0(e.offset),e.msg)
658 except TryNext:
656 except TryNext:
659 warn('Could not open editor')
657 warn('Could not open editor')
660 return False
658 return False
661 return True
659 return True
662
660
663 #-------------------------------------------------------------------------
661 #-------------------------------------------------------------------------
664 # Things related to exiting
662 # Things related to exiting
665 #-------------------------------------------------------------------------
663 #-------------------------------------------------------------------------
666
664
667 def ask_exit(self):
665 def ask_exit(self):
668 """ Ask the shell to exit. Can be overiden and used as a callback. """
666 """ Ask the shell to exit. Can be overiden and used as a callback. """
669 self.exit_now = True
667 self.exit_now = True
670
668
671 def exit(self):
669 def exit(self):
672 """Handle interactive exit.
670 """Handle interactive exit.
673
671
674 This method calls the ask_exit callback."""
672 This method calls the ask_exit callback."""
675 if self.confirm_exit:
673 if self.confirm_exit:
676 if self.ask_yes_no('Do you really want to exit ([y]/n)?','y'):
674 if self.ask_yes_no('Do you really want to exit ([y]/n)?','y'):
677 self.ask_exit()
675 self.ask_exit()
678 else:
676 else:
679 self.ask_exit()
677 self.ask_exit()
680
678
681 #-------------------------------------------------------------------------
679 #-------------------------------------------------------------------------
682 # Things related to magics
680 # Things related to magics
683 #-------------------------------------------------------------------------
681 #-------------------------------------------------------------------------
684
682
685 def init_magics(self):
683 def init_magics(self):
686 super(TerminalInteractiveShell, self).init_magics()
684 super(TerminalInteractiveShell, self).init_magics()
687 self.register_magics(TerminalMagics)
685 self.register_magics(TerminalMagics)
688
686
689 def showindentationerror(self):
687 def showindentationerror(self):
690 super(TerminalInteractiveShell, self).showindentationerror()
688 super(TerminalInteractiveShell, self).showindentationerror()
691 if not self.using_paste_magics:
689 if not self.using_paste_magics:
692 print("If you want to paste code into IPython, try the "
690 print("If you want to paste code into IPython, try the "
693 "%paste and %cpaste magic functions.")
691 "%paste and %cpaste magic functions.")
694
692
695
693
696 InteractiveShellABC.register(TerminalInteractiveShell)
694 InteractiveShellABC.register(TerminalInteractiveShell)
@@ -1,400 +1,400 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 """
3 """
4 The :class:`~IPython.core.application.Application` object for the command
4 The :class:`~IPython.core.application.Application` object for the command
5 line :command:`ipython` program.
5 line :command:`ipython` program.
6
6
7 Authors
7 Authors
8 -------
8 -------
9
9
10 * Brian Granger
10 * Brian Granger
11 * Fernando Perez
11 * Fernando Perez
12 * Min Ragan-Kelley
12 * Min Ragan-Kelley
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 from __future__ import absolute_import
26 from __future__ import absolute_import
27
27
28 import logging
28 import logging
29 import os
29 import os
30 import sys
30 import sys
31
31
32 from IPython.config.loader import (
32 from IPython.config.loader import (
33 Config, PyFileConfigLoader, ConfigFileNotFound
33 Config, PyFileConfigLoader, ConfigFileNotFound
34 )
34 )
35 from IPython.config.application import boolean_flag, catch_config_error
35 from IPython.config.application import boolean_flag, catch_config_error
36 from IPython.core import release
36 from IPython.core import release
37 from IPython.core import usage
37 from IPython.core import usage
38 from IPython.core.completer import IPCompleter
38 from IPython.core.completer import IPCompleter
39 from IPython.core.crashhandler import CrashHandler
39 from IPython.core.crashhandler import CrashHandler
40 from IPython.core.formatters import PlainTextFormatter
40 from IPython.core.formatters import PlainTextFormatter
41 from IPython.core.history import HistoryManager
41 from IPython.core.history import HistoryManager
42 from IPython.core.prompts import PromptManager
42 from IPython.core.prompts import PromptManager
43 from IPython.core.application import (
43 from IPython.core.application import (
44 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
44 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
45 )
45 )
46 from IPython.core.magics import ScriptMagics
46 from IPython.core.magics import ScriptMagics
47 from IPython.core.shellapp import (
47 from IPython.core.shellapp import (
48 InteractiveShellApp, shell_flags, shell_aliases
48 InteractiveShellApp, shell_flags, shell_aliases
49 )
49 )
50 from IPython.terminal.interactiveshell import TerminalInteractiveShell
50 from IPython.terminal.interactiveshell import TerminalInteractiveShell
51 from IPython.utils import warn
51 from IPython.utils import warn
52 from IPython.utils.path import get_ipython_dir, check_for_old_config
52 from IPython.utils.path import get_ipython_dir, check_for_old_config
53 from IPython.utils.traitlets import (
53 from IPython.utils.traitlets import (
54 Bool, List, Dict, CaselessStrEnum
54 Bool, List, Dict,
55 )
55 )
56
56
57 #-----------------------------------------------------------------------------
57 #-----------------------------------------------------------------------------
58 # Globals, utilities and helpers
58 # Globals, utilities and helpers
59 #-----------------------------------------------------------------------------
59 #-----------------------------------------------------------------------------
60
60
61 #: The default config file name for this application.
61 #: The default config file name for this application.
62 default_config_file_name = u'ipython_config.py'
62 default_config_file_name = u'ipython_config.py'
63
63
64 _examples = """
64 _examples = """
65 ipython --pylab # start in pylab mode
65 ipython --pylab # start in pylab mode
66 ipython --pylab=qt # start in pylab mode with the qt4 backend
66 ipython --pylab=qt # start in pylab mode with the qt4 backend
67 ipython --log-level=DEBUG # set logging to DEBUG
67 ipython --log-level=DEBUG # set logging to DEBUG
68 ipython --profile=foo # start with profile foo
68 ipython --profile=foo # start with profile foo
69
69
70 ipython qtconsole # start the qtconsole GUI application
70 ipython qtconsole # start the qtconsole GUI application
71 ipython help qtconsole # show the help for the qtconsole subcmd
71 ipython help qtconsole # show the help for the qtconsole subcmd
72
72
73 ipython console # start the terminal-based console application
73 ipython console # start the terminal-based console application
74 ipython help console # show the help for the console subcmd
74 ipython help console # show the help for the console subcmd
75
75
76 ipython notebook # start the IPython notebook
76 ipython notebook # start the IPython notebook
77 ipython help notebook # show the help for the notebook subcmd
77 ipython help notebook # show the help for the notebook subcmd
78
78
79 ipython profile create foo # create profile foo w/ default config files
79 ipython profile create foo # create profile foo w/ default config files
80 ipython help profile # show the help for the profile subcmd
80 ipython help profile # show the help for the profile subcmd
81
81
82 ipython locate # print the path to the IPython directory
82 ipython locate # print the path to the IPython directory
83 ipython locate profile foo # print the path to the directory for profile `foo`
83 ipython locate profile foo # print the path to the directory for profile `foo`
84
84
85 ipython nbconvert # convert notebooks to/from other formats
85 ipython nbconvert # convert notebooks to/from other formats
86 """
86 """
87
87
88 #-----------------------------------------------------------------------------
88 #-----------------------------------------------------------------------------
89 # Crash handler for this application
89 # Crash handler for this application
90 #-----------------------------------------------------------------------------
90 #-----------------------------------------------------------------------------
91
91
92 class IPAppCrashHandler(CrashHandler):
92 class IPAppCrashHandler(CrashHandler):
93 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
93 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
94
94
95 def __init__(self, app):
95 def __init__(self, app):
96 contact_name = release.author
96 contact_name = release.author
97 contact_email = release.author_email
97 contact_email = release.author_email
98 bug_tracker = 'https://github.com/ipython/ipython/issues'
98 bug_tracker = 'https://github.com/ipython/ipython/issues'
99 super(IPAppCrashHandler,self).__init__(
99 super(IPAppCrashHandler,self).__init__(
100 app, contact_name, contact_email, bug_tracker
100 app, contact_name, contact_email, bug_tracker
101 )
101 )
102
102
103 def make_report(self,traceback):
103 def make_report(self,traceback):
104 """Return a string containing a crash report."""
104 """Return a string containing a crash report."""
105
105
106 sec_sep = self.section_sep
106 sec_sep = self.section_sep
107 # Start with parent report
107 # Start with parent report
108 report = [super(IPAppCrashHandler, self).make_report(traceback)]
108 report = [super(IPAppCrashHandler, self).make_report(traceback)]
109 # Add interactive-specific info we may have
109 # Add interactive-specific info we may have
110 rpt_add = report.append
110 rpt_add = report.append
111 try:
111 try:
112 rpt_add(sec_sep+"History of session input:")
112 rpt_add(sec_sep+"History of session input:")
113 for line in self.app.shell.user_ns['_ih']:
113 for line in self.app.shell.user_ns['_ih']:
114 rpt_add(line)
114 rpt_add(line)
115 rpt_add('\n*** Last line of input (may not be in above history):\n')
115 rpt_add('\n*** Last line of input (may not be in above history):\n')
116 rpt_add(self.app.shell._last_input_line+'\n')
116 rpt_add(self.app.shell._last_input_line+'\n')
117 except:
117 except:
118 pass
118 pass
119
119
120 return ''.join(report)
120 return ''.join(report)
121
121
122 #-----------------------------------------------------------------------------
122 #-----------------------------------------------------------------------------
123 # Aliases and Flags
123 # Aliases and Flags
124 #-----------------------------------------------------------------------------
124 #-----------------------------------------------------------------------------
125 flags = dict(base_flags)
125 flags = dict(base_flags)
126 flags.update(shell_flags)
126 flags.update(shell_flags)
127 frontend_flags = {}
127 frontend_flags = {}
128 addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
128 addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
129 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
129 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
130 'Turn on auto editing of files with syntax errors.',
130 'Turn on auto editing of files with syntax errors.',
131 'Turn off auto editing of files with syntax errors.'
131 'Turn off auto editing of files with syntax errors.'
132 )
132 )
133 addflag('banner', 'TerminalIPythonApp.display_banner',
133 addflag('banner', 'TerminalIPythonApp.display_banner',
134 "Display a banner upon starting IPython.",
134 "Display a banner upon starting IPython.",
135 "Don't display a banner upon starting IPython."
135 "Don't display a banner upon starting IPython."
136 )
136 )
137 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
137 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
138 """Set to confirm when you try to exit IPython with an EOF (Control-D
138 """Set to confirm when you try to exit IPython with an EOF (Control-D
139 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
139 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
140 you can force a direct exit without any confirmation.""",
140 you can force a direct exit without any confirmation.""",
141 "Don't prompt the user when exiting."
141 "Don't prompt the user when exiting."
142 )
142 )
143 addflag('term-title', 'TerminalInteractiveShell.term_title',
143 addflag('term-title', 'TerminalInteractiveShell.term_title',
144 "Enable auto setting the terminal title.",
144 "Enable auto setting the terminal title.",
145 "Disable auto setting the terminal title."
145 "Disable auto setting the terminal title."
146 )
146 )
147 classic_config = Config()
147 classic_config = Config()
148 classic_config.InteractiveShell.cache_size = 0
148 classic_config.InteractiveShell.cache_size = 0
149 classic_config.PlainTextFormatter.pprint = False
149 classic_config.PlainTextFormatter.pprint = False
150 classic_config.PromptManager.in_template = '>>> '
150 classic_config.PromptManager.in_template = '>>> '
151 classic_config.PromptManager.in2_template = '... '
151 classic_config.PromptManager.in2_template = '... '
152 classic_config.PromptManager.out_template = ''
152 classic_config.PromptManager.out_template = ''
153 classic_config.InteractiveShell.separate_in = ''
153 classic_config.InteractiveShell.separate_in = ''
154 classic_config.InteractiveShell.separate_out = ''
154 classic_config.InteractiveShell.separate_out = ''
155 classic_config.InteractiveShell.separate_out2 = ''
155 classic_config.InteractiveShell.separate_out2 = ''
156 classic_config.InteractiveShell.colors = 'NoColor'
156 classic_config.InteractiveShell.colors = 'NoColor'
157 classic_config.InteractiveShell.xmode = 'Plain'
157 classic_config.InteractiveShell.xmode = 'Plain'
158
158
159 frontend_flags['classic']=(
159 frontend_flags['classic']=(
160 classic_config,
160 classic_config,
161 "Gives IPython a similar feel to the classic Python prompt."
161 "Gives IPython a similar feel to the classic Python prompt."
162 )
162 )
163 # # log doesn't make so much sense this way anymore
163 # # log doesn't make so much sense this way anymore
164 # paa('--log','-l',
164 # paa('--log','-l',
165 # action='store_true', dest='InteractiveShell.logstart',
165 # action='store_true', dest='InteractiveShell.logstart',
166 # help="Start logging to the default log file (./ipython_log.py).")
166 # help="Start logging to the default log file (./ipython_log.py).")
167 #
167 #
168 # # quick is harder to implement
168 # # quick is harder to implement
169 frontend_flags['quick']=(
169 frontend_flags['quick']=(
170 {'TerminalIPythonApp' : {'quick' : True}},
170 {'TerminalIPythonApp' : {'quick' : True}},
171 "Enable quick startup with no config files."
171 "Enable quick startup with no config files."
172 )
172 )
173
173
174 frontend_flags['i'] = (
174 frontend_flags['i'] = (
175 {'TerminalIPythonApp' : {'force_interact' : True}},
175 {'TerminalIPythonApp' : {'force_interact' : True}},
176 """If running code from the command line, become interactive afterwards.
176 """If running code from the command line, become interactive afterwards.
177 Note: can also be given simply as '-i.'"""
177 Note: can also be given simply as '-i.'"""
178 )
178 )
179 flags.update(frontend_flags)
179 flags.update(frontend_flags)
180
180
181 aliases = dict(base_aliases)
181 aliases = dict(base_aliases)
182 aliases.update(shell_aliases)
182 aliases.update(shell_aliases)
183
183
184 #-----------------------------------------------------------------------------
184 #-----------------------------------------------------------------------------
185 # Main classes and functions
185 # Main classes and functions
186 #-----------------------------------------------------------------------------
186 #-----------------------------------------------------------------------------
187
187
188
188
189 class LocateIPythonApp(BaseIPythonApplication):
189 class LocateIPythonApp(BaseIPythonApplication):
190 description = """print the path to the IPython dir"""
190 description = """print the path to the IPython dir"""
191 subcommands = Dict(dict(
191 subcommands = Dict(dict(
192 profile=('IPython.core.profileapp.ProfileLocate',
192 profile=('IPython.core.profileapp.ProfileLocate',
193 "print the path to an IPython profile directory",
193 "print the path to an IPython profile directory",
194 ),
194 ),
195 ))
195 ))
196 def start(self):
196 def start(self):
197 if self.subapp is not None:
197 if self.subapp is not None:
198 return self.subapp.start()
198 return self.subapp.start()
199 else:
199 else:
200 print self.ipython_dir
200 print self.ipython_dir
201
201
202
202
203 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
203 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
204 name = u'ipython'
204 name = u'ipython'
205 description = usage.cl_usage
205 description = usage.cl_usage
206 default_config_file_name = default_config_file_name
206 default_config_file_name = default_config_file_name
207 crash_handler_class = IPAppCrashHandler
207 crash_handler_class = IPAppCrashHandler
208 examples = _examples
208 examples = _examples
209
209
210 flags = Dict(flags)
210 flags = Dict(flags)
211 aliases = Dict(aliases)
211 aliases = Dict(aliases)
212 classes = List()
212 classes = List()
213 def _classes_default(self):
213 def _classes_default(self):
214 """This has to be in a method, for TerminalIPythonApp to be available."""
214 """This has to be in a method, for TerminalIPythonApp to be available."""
215 return [
215 return [
216 InteractiveShellApp, # ShellApp comes before TerminalApp, because
216 InteractiveShellApp, # ShellApp comes before TerminalApp, because
217 self.__class__, # it will also affect subclasses (e.g. QtConsole)
217 self.__class__, # it will also affect subclasses (e.g. QtConsole)
218 TerminalInteractiveShell,
218 TerminalInteractiveShell,
219 PromptManager,
219 PromptManager,
220 HistoryManager,
220 HistoryManager,
221 ProfileDir,
221 ProfileDir,
222 PlainTextFormatter,
222 PlainTextFormatter,
223 IPCompleter,
223 IPCompleter,
224 ScriptMagics,
224 ScriptMagics,
225 ]
225 ]
226
226
227 subcommands = Dict(dict(
227 subcommands = Dict(dict(
228 qtconsole=('IPython.qt.console.qtconsoleapp.IPythonQtConsoleApp',
228 qtconsole=('IPython.qt.console.qtconsoleapp.IPythonQtConsoleApp',
229 """Launch the IPython Qt Console."""
229 """Launch the IPython Qt Console."""
230 ),
230 ),
231 notebook=('IPython.html.notebookapp.NotebookApp',
231 notebook=('IPython.html.notebookapp.NotebookApp',
232 """Launch the IPython HTML Notebook Server."""
232 """Launch the IPython HTML Notebook Server."""
233 ),
233 ),
234 profile = ("IPython.core.profileapp.ProfileApp",
234 profile = ("IPython.core.profileapp.ProfileApp",
235 "Create and manage IPython profiles."
235 "Create and manage IPython profiles."
236 ),
236 ),
237 kernel = ("IPython.kernel.zmq.kernelapp.IPKernelApp",
237 kernel = ("IPython.kernel.zmq.kernelapp.IPKernelApp",
238 "Start a kernel without an attached frontend."
238 "Start a kernel without an attached frontend."
239 ),
239 ),
240 console=('IPython.terminal.console.app.ZMQTerminalIPythonApp',
240 console=('IPython.terminal.console.app.ZMQTerminalIPythonApp',
241 """Launch the IPython terminal-based Console."""
241 """Launch the IPython terminal-based Console."""
242 ),
242 ),
243 locate=('IPython.terminal.ipapp.LocateIPythonApp',
243 locate=('IPython.terminal.ipapp.LocateIPythonApp',
244 LocateIPythonApp.description
244 LocateIPythonApp.description
245 ),
245 ),
246 history=('IPython.core.historyapp.HistoryApp',
246 history=('IPython.core.historyapp.HistoryApp',
247 "Manage the IPython history database."
247 "Manage the IPython history database."
248 ),
248 ),
249 nbconvert=('IPython.nbconvert.nbconvertapp.NbConvertApp',
249 nbconvert=('IPython.nbconvert.nbconvertapp.NbConvertApp',
250 "Convert notebooks to/from other formats."
250 "Convert notebooks to/from other formats."
251 ),
251 ),
252 ))
252 ))
253
253
254 # *do* autocreate requested profile, but don't create the config file.
254 # *do* autocreate requested profile, but don't create the config file.
255 auto_create=Bool(True)
255 auto_create=Bool(True)
256 # configurables
256 # configurables
257 ignore_old_config=Bool(False, config=True,
257 ignore_old_config=Bool(False, config=True,
258 help="Suppress warning messages about legacy config files"
258 help="Suppress warning messages about legacy config files"
259 )
259 )
260 quick = Bool(False, config=True,
260 quick = Bool(False, config=True,
261 help="""Start IPython quickly by skipping the loading of config files."""
261 help="""Start IPython quickly by skipping the loading of config files."""
262 )
262 )
263 def _quick_changed(self, name, old, new):
263 def _quick_changed(self, name, old, new):
264 if new:
264 if new:
265 self.load_config_file = lambda *a, **kw: None
265 self.load_config_file = lambda *a, **kw: None
266 self.ignore_old_config=True
266 self.ignore_old_config=True
267
267
268 display_banner = Bool(True, config=True,
268 display_banner = Bool(True, config=True,
269 help="Whether to display a banner upon starting IPython."
269 help="Whether to display a banner upon starting IPython."
270 )
270 )
271
271
272 # if there is code of files to run from the cmd line, don't interact
272 # if there is code of files to run from the cmd line, don't interact
273 # unless the --i flag (App.force_interact) is true.
273 # unless the --i flag (App.force_interact) is true.
274 force_interact = Bool(False, config=True,
274 force_interact = Bool(False, config=True,
275 help="""If a command or file is given via the command-line,
275 help="""If a command or file is given via the command-line,
276 e.g. 'ipython foo.py"""
276 e.g. 'ipython foo.py"""
277 )
277 )
278 def _force_interact_changed(self, name, old, new):
278 def _force_interact_changed(self, name, old, new):
279 if new:
279 if new:
280 self.interact = True
280 self.interact = True
281
281
282 def _file_to_run_changed(self, name, old, new):
282 def _file_to_run_changed(self, name, old, new):
283 if new:
283 if new:
284 self.something_to_run = True
284 self.something_to_run = True
285 if new and not self.force_interact:
285 if new and not self.force_interact:
286 self.interact = False
286 self.interact = False
287 _code_to_run_changed = _file_to_run_changed
287 _code_to_run_changed = _file_to_run_changed
288 _module_to_run_changed = _file_to_run_changed
288 _module_to_run_changed = _file_to_run_changed
289
289
290 # internal, not-configurable
290 # internal, not-configurable
291 interact=Bool(True)
291 interact=Bool(True)
292 something_to_run=Bool(False)
292 something_to_run=Bool(False)
293
293
294 def parse_command_line(self, argv=None):
294 def parse_command_line(self, argv=None):
295 """override to allow old '-pylab' flag with deprecation warning"""
295 """override to allow old '-pylab' flag with deprecation warning"""
296
296
297 argv = sys.argv[1:] if argv is None else argv
297 argv = sys.argv[1:] if argv is None else argv
298
298
299 if '-pylab' in argv:
299 if '-pylab' in argv:
300 # deprecated `-pylab` given,
300 # deprecated `-pylab` given,
301 # warn and transform into current syntax
301 # warn and transform into current syntax
302 argv = argv[:] # copy, don't clobber
302 argv = argv[:] # copy, don't clobber
303 idx = argv.index('-pylab')
303 idx = argv.index('-pylab')
304 warn.warn("`-pylab` flag has been deprecated.\n"
304 warn.warn("`-pylab` flag has been deprecated.\n"
305 " Use `--pylab` instead, or `--pylab=foo` to specify a backend.")
305 " Use `--pylab` instead, or `--pylab=foo` to specify a backend.")
306 sub = '--pylab'
306 sub = '--pylab'
307 if len(argv) > idx+1:
307 if len(argv) > idx+1:
308 # check for gui arg, as in '-pylab qt'
308 # check for gui arg, as in '-pylab qt'
309 gui = argv[idx+1]
309 gui = argv[idx+1]
310 if gui in ('wx', 'qt', 'qt4', 'gtk', 'auto'):
310 if gui in ('wx', 'qt', 'qt4', 'gtk', 'auto'):
311 sub = '--pylab='+gui
311 sub = '--pylab='+gui
312 argv.pop(idx+1)
312 argv.pop(idx+1)
313 argv[idx] = sub
313 argv[idx] = sub
314
314
315 return super(TerminalIPythonApp, self).parse_command_line(argv)
315 return super(TerminalIPythonApp, self).parse_command_line(argv)
316
316
317 @catch_config_error
317 @catch_config_error
318 def initialize(self, argv=None):
318 def initialize(self, argv=None):
319 """Do actions after construct, but before starting the app."""
319 """Do actions after construct, but before starting the app."""
320 super(TerminalIPythonApp, self).initialize(argv)
320 super(TerminalIPythonApp, self).initialize(argv)
321 if self.subapp is not None:
321 if self.subapp is not None:
322 # don't bother initializing further, starting subapp
322 # don't bother initializing further, starting subapp
323 return
323 return
324 if not self.ignore_old_config:
324 if not self.ignore_old_config:
325 check_for_old_config(self.ipython_dir)
325 check_for_old_config(self.ipython_dir)
326 # print self.extra_args
326 # print self.extra_args
327 if self.extra_args and not self.something_to_run:
327 if self.extra_args and not self.something_to_run:
328 self.file_to_run = self.extra_args[0]
328 self.file_to_run = self.extra_args[0]
329 self.init_path()
329 self.init_path()
330 # create the shell
330 # create the shell
331 self.init_shell()
331 self.init_shell()
332 # and draw the banner
332 # and draw the banner
333 self.init_banner()
333 self.init_banner()
334 # Now a variety of things that happen after the banner is printed.
334 # Now a variety of things that happen after the banner is printed.
335 self.init_gui_pylab()
335 self.init_gui_pylab()
336 self.init_extensions()
336 self.init_extensions()
337 self.init_code()
337 self.init_code()
338
338
339 def init_shell(self):
339 def init_shell(self):
340 """initialize the InteractiveShell instance"""
340 """initialize the InteractiveShell instance"""
341 # Create an InteractiveShell instance.
341 # Create an InteractiveShell instance.
342 # shell.display_banner should always be False for the terminal
342 # shell.display_banner should always be False for the terminal
343 # based app, because we call shell.show_banner() by hand below
343 # based app, because we call shell.show_banner() by hand below
344 # so the banner shows *before* all extension loading stuff.
344 # so the banner shows *before* all extension loading stuff.
345 self.shell = TerminalInteractiveShell.instance(parent=self,
345 self.shell = TerminalInteractiveShell.instance(parent=self,
346 display_banner=False, profile_dir=self.profile_dir,
346 display_banner=False, profile_dir=self.profile_dir,
347 ipython_dir=self.ipython_dir)
347 ipython_dir=self.ipython_dir)
348 self.shell.configurables.append(self)
348 self.shell.configurables.append(self)
349
349
350 def init_banner(self):
350 def init_banner(self):
351 """optionally display the banner"""
351 """optionally display the banner"""
352 if self.display_banner and self.interact:
352 if self.display_banner and self.interact:
353 self.shell.show_banner()
353 self.shell.show_banner()
354 # Make sure there is a space below the banner.
354 # Make sure there is a space below the banner.
355 if self.log_level <= logging.INFO: print
355 if self.log_level <= logging.INFO: print
356
356
357 def _pylab_changed(self, name, old, new):
357 def _pylab_changed(self, name, old, new):
358 """Replace --pylab='inline' with --pylab='auto'"""
358 """Replace --pylab='inline' with --pylab='auto'"""
359 if new == 'inline':
359 if new == 'inline':
360 warn.warn("'inline' not available as pylab backend, "
360 warn.warn("'inline' not available as pylab backend, "
361 "using 'auto' instead.")
361 "using 'auto' instead.")
362 self.pylab = 'auto'
362 self.pylab = 'auto'
363
363
364 def start(self):
364 def start(self):
365 if self.subapp is not None:
365 if self.subapp is not None:
366 return self.subapp.start()
366 return self.subapp.start()
367 # perform any prexec steps:
367 # perform any prexec steps:
368 if self.interact:
368 if self.interact:
369 self.log.debug("Starting IPython's mainloop...")
369 self.log.debug("Starting IPython's mainloop...")
370 self.shell.mainloop()
370 self.shell.mainloop()
371 else:
371 else:
372 self.log.debug("IPython not interactive...")
372 self.log.debug("IPython not interactive...")
373
373
374
374
375 def load_default_config(ipython_dir=None):
375 def load_default_config(ipython_dir=None):
376 """Load the default config file from the default ipython_dir.
376 """Load the default config file from the default ipython_dir.
377
377
378 This is useful for embedded shells.
378 This is useful for embedded shells.
379 """
379 """
380 if ipython_dir is None:
380 if ipython_dir is None:
381 ipython_dir = get_ipython_dir()
381 ipython_dir = get_ipython_dir()
382 profile_dir = os.path.join(ipython_dir, 'profile_default')
382 profile_dir = os.path.join(ipython_dir, 'profile_default')
383 cl = PyFileConfigLoader(default_config_file_name, profile_dir)
383 cl = PyFileConfigLoader(default_config_file_name, profile_dir)
384 try:
384 try:
385 config = cl.load_config()
385 config = cl.load_config()
386 except ConfigFileNotFound:
386 except ConfigFileNotFound:
387 # no config found
387 # no config found
388 config = Config()
388 config = Config()
389 return config
389 return config
390
390
391
391
392 def launch_new_instance():
392 def launch_new_instance():
393 """Create and run a full blown IPython instance"""
393 """Create and run a full blown IPython instance"""
394 app = TerminalIPythonApp.instance()
394 app = TerminalIPythonApp.instance()
395 app.initialize()
395 app.initialize()
396 app.start()
396 app.start()
397
397
398
398
399 if __name__ == '__main__':
399 if __name__ == '__main__':
400 launch_new_instance()
400 launch_new_instance()
General Comments 0
You need to be logged in to leave comments. Login now