##// END OF EJS Templates
zmqterminal subclasses TerminalInteractiveShell/IPApp...
MinRK -
Show More
@@ -0,0 +1,161 b''
1 from __future__ import print_function
2
3 import signal
4 import sys
5 import time
6
7 from IPython.frontend.terminal.ipapp import TerminalIPythonApp
8
9 from IPython.utils.traitlets import (
10 Dict, List, Unicode, Int, CaselessStrEnum, CBool, Any
11 )
12 from IPython.zmq.ipkernel import (
13 flags as ipkernel_flags,
14 aliases as ipkernel_aliases,
15 IPKernelApp
16 )
17 from IPython.zmq.session import Session
18 from IPython.zmq.zmqshell import ZMQInteractiveShell
19 from IPython.zmq.blockingkernelmanager import BlockingKernelManager
20 from IPython.zmq.ipkernel import (
21 flags as ipkernel_flags,
22 aliases as ipkernel_aliases,
23 IPKernelApp
24 )
25 from IPython.frontend.zmqterminal.interactiveshell import ZMQTerminalInteractiveShell
26
27 #-----------------------------------------------------------------------------
28 # Network Constants
29 #-----------------------------------------------------------------------------
30
31 from IPython.utils.localinterfaces import LOCALHOST, LOCAL_IPS
32
33 #-----------------------------------------------------------------------------
34 # Flags and Aliases
35 #-----------------------------------------------------------------------------
36
37
38 flags = dict(ipkernel_flags)
39 frontend_flags = {
40 'existing' : ({'ZMQTerminalIPythonApp' : {'existing' : True}},
41 "Connect to an existing kernel."),
42 }
43 flags.update(frontend_flags)
44 # the flags that are specific to the frontend
45 # these must be scrubbed before being passed to the kernel,
46 # or it will raise an error on unrecognized flags
47 frontend_flags = frontend_flags.keys()
48
49 aliases = dict(ipkernel_aliases)
50
51 frontend_aliases = dict(
52 hb = 'ZMQTerminalIPythonApp.hb_port',
53 shell = 'ZMQTerminalIPythonApp.shell_port',
54 iopub = 'ZMQTerminalIPythonApp.iopub_port',
55 stdin = 'ZMQTerminalIPythonApp.stdin_port',
56 ip = 'ZMQTerminalIPythonApp.ip',
57 )
58 aliases.update(frontend_aliases)
59 # also scrub aliases from the frontend
60 frontend_flags.extend(frontend_aliases.keys())
61
62 #-----------------------------------------------------------------------------
63 # Classes
64 #-----------------------------------------------------------------------------
65
66
67 class ZMQTerminalIPythonApp(TerminalIPythonApp):
68 """Start a terminal frontend to the IPython zmq kernel."""
69
70 kernel_argv = List(Unicode)
71 flags = Dict(flags)
72 aliases = Dict(aliases)
73 classes = List([IPKernelApp, ZMQTerminalInteractiveShell])
74
75 # connection info:
76 ip = Unicode(LOCALHOST, config=True,
77 help="""Set the kernel\'s IP address [default localhost].
78 If the IP address is something other than localhost, then
79 Consoles on other machines will be able to connect
80 to the Kernel, so be careful!"""
81 )
82 pure = False
83 hb_port = Int(0, config=True,
84 help="set the heartbeat port [default: random]")
85 shell_port = Int(0, config=True,
86 help="set the shell (XREP) port [default: random]")
87 iopub_port = Int(0, config=True,
88 help="set the iopub (PUB) port [default: random]")
89 stdin_port = Int(0, config=True,
90 help="set the stdin (XREQ) port [default: random]")
91
92 existing = CBool(False, config=True,
93 help="Whether to connect to an already running Kernel.")
94
95 # from qtconsoleapp:
96 def parse_command_line(self, argv=None):
97 super(ZMQTerminalIPythonApp, self).parse_command_line(argv)
98 if argv is None:
99 argv = sys.argv[1:]
100
101 self.kernel_argv = list(argv) # copy
102 # kernel should inherit default config file from frontend
103 self.kernel_argv.append("--KernelApp.parent_appname='%s'"%self.name)
104 # scrub frontend-specific flags
105 for a in argv:
106
107 if a.startswith('-'):
108 key = a.lstrip('-').split('=')[0]
109 if key in frontend_flags:
110 self.kernel_argv.remove(a)
111
112 def init_kernel_manager(self):
113 """init kernel manager (from qtconsole)"""
114 # Don't let Qt or ZMQ swallow KeyboardInterupts.
115 # signal.signal(signal.SIGINT, signal.SIG_DFL)
116
117 # Create a KernelManager and start a kernel.
118 self.kernel_manager = BlockingKernelManager(
119 shell_address=(self.ip, self.shell_port),
120 sub_address=(self.ip, self.iopub_port),
121 stdin_address=(self.ip, self.stdin_port),
122 hb_address=(self.ip, self.hb_port),
123 config=self.config
124 )
125 # start the kernel
126 if not self.existing:
127 kwargs = dict(ip=self.ip, ipython=not self.pure)
128 kwargs['extra_arguments'] = self.kernel_argv
129 self.kernel_manager.start_kernel(**kwargs)
130 # wait for kernel to start
131 time.sleep(0.5)
132 self.kernel_manager.start_channels()
133 # relay sigint to kernel
134 signal.signal(signal.SIGINT, self.handle_sigint)
135
136 def init_shell(self):
137 self.init_kernel_manager()
138 self.shell = ZMQTerminalInteractiveShell.instance(config=self.config,
139 display_banner=False, profile_dir=self.profile_dir,
140 ipython_dir=self.ipython_dir, kernel_manager=self.kernel_manager)
141
142 def handle_sigint(self, *args):
143 # FIXME: this doesn't work, the kernel just dies every time
144 self.shell.write('KeyboardInterrupt\n')
145 self.kernel_manager.interrupt_kernel()
146
147 def init_code(self):
148 # no-op in the frontend, code gets run in the backend
149 pass
150
151
152 def launch_new_instance():
153 """Create and run a full blown IPython instance"""
154 app = ZMQTerminalIPythonApp.instance()
155 app.initialize()
156 app.start()
157
158
159 if __name__ == '__main__':
160 launch_new_instance()
161
@@ -0,0 +1,252 b''
1 # -*- coding: utf-8 -*-
2 """Frontend of ipython working with python-zmq
3
4 Ipython's frontend, is a ipython interface that send request to kernel and proccess the kernel's outputs.
5
6 For more details, see the ipython-zmq design
7 """
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2011 The IPython Development Team
10 #
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
13 #-----------------------------------------------------------------------------
14
15 #-----------------------------------------------------------------------------
16 # Imports
17 #-----------------------------------------------------------------------------
18 from __future__ import print_function
19
20 import bdb
21 import sys
22
23 from Queue import Empty
24
25 from IPython.core.alias import AliasManager, AliasError
26 from IPython.utils.warn import warn, error, fatal
27 from IPython.utils import io
28
29 from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
30 from IPython.frontend.zmqterminal.completer import ZMQCompleter
31
32
33 class ZMQTerminalInteractiveShell(TerminalInteractiveShell):
34 """A subclass of TerminalInteractiveShell that """
35
36 def __init__(self, *args, **kwargs):
37 self.km = kwargs.pop('kernel_manager')
38 self.session_id = self.km.session.session
39 super(ZMQTerminalInteractiveShell, self).__init__(*args, **kwargs)
40
41 def init_completer(self):
42 """Initialize the completion machinery.
43
44 This creates completion machinery that can be used by client code,
45 either interactively in-process (typically triggered by the readline
46 library), programatically (such as in test suites) or out-of-prcess
47 (typically over the network by remote frontends).
48 """
49 from IPython.core.completerlib import (module_completer,
50 magic_run_completer, cd_completer)
51
52 self.Completer = ZMQCompleter(self, self.km)
53
54
55 self.set_hook('complete_command', module_completer, str_key = 'import')
56 self.set_hook('complete_command', module_completer, str_key = 'from')
57 self.set_hook('complete_command', magic_run_completer, str_key = '%run')
58 self.set_hook('complete_command', cd_completer, str_key = '%cd')
59
60 # Only configure readline if we truly are using readline. IPython can
61 # do tab-completion over the network, in GUIs, etc, where readline
62 # itself may be absent
63 if self.has_readline:
64 self.set_readline_completer()
65
66 def run_cell(self, cell, store_history=True):
67 """Run a complete IPython cell.
68
69 Parameters
70 ----------
71 cell : str
72 The code (including IPython code such as %magic functions) to run.
73 store_history : bool
74 If True, the raw and translated cell will be stored in IPython's
75 history. For user code calling back into IPython's machinery, this
76 should be set to False.
77 """
78 if (not cell) or cell.isspace():
79 return
80
81 # shell_channel.execute takes 'hidden', which is the inverse of store_hist
82 msg_id = self.km.shell_channel.execute(cell, not store_history)
83 while not self.km.shell_channel.msg_ready():
84 try:
85 self.handle_stdin_request(timeout=0.05)
86 except Empty:
87 pass
88 self.handle_execute_reply(msg_id)
89
90 #-----------------
91 # message handlers
92 #-----------------
93
94 def handle_execute_reply(self, msg_id):
95 msg = self.km.shell_channel.get_msg()
96 if msg["parent_header"]["msg_id"] == msg_id:
97 if msg["content"]["status"] == 'ok' :
98 self.handle_iopub()
99
100 elif msg["content"]["status"] == 'error':
101 for frame in msg["content"]["traceback"]:
102 print(frame, file=io.stderr)
103
104 self.execution_count = msg["content"]["execution_count"] + 1
105
106
107 def handle_iopub(self):
108 """ Method to procces subscribe channel's messages
109
110 This method reads a message and processes the content in different
111 outputs like stdout, stderr, pyout and status
112
113 Arguments:
114 sub_msg: message receive from kernel in the sub socket channel
115 capture by kernel manager.
116 """
117 while self.km.sub_channel.msg_ready():
118 sub_msg = self.km.sub_channel.get_msg()
119 msg_type = sub_msg['header']['msg_type']
120 if self.session_id == sub_msg['parent_header']['session']:
121 if msg_type == 'status' :
122 if sub_msg["content"]["execution_state"] == "busy" :
123 pass
124
125 elif msg_type == 'stream' :
126 if sub_msg["content"]["name"] == "stdout":
127 print(sub_msg["content"]["data"], file=io.stdout, end="")
128 io.stdout.flush()
129 elif sub_msg["content"]["name"] == "stderr" :
130 print(sub_msg["content"]["data"], file=io.stderr, end="")
131 io.stderr.flush()
132
133 elif msg_type == 'pyout':
134 format_dict = sub_msg["content"]["data"]
135 # taken from DisplayHook.__call__:
136 hook = self.displayhook
137 hook.start_displayhook()
138 hook.write_output_prompt()
139 hook.write_format_data(format_dict)
140 hook.log_output(format_dict)
141 hook.finish_displayhook()
142
143 def handle_stdin_request(self, timeout=0.1):
144 """ Method to capture raw_input
145 """
146 msg_rep = self.km.stdin_channel.get_msg(timeout=timeout)
147 if self.session_id == msg_rep["parent_header"]["session"] :
148 raw_data = raw_input(msg_rep["content"]["prompt"])
149 self.km.stdin_channel.input(raw_data)
150
151 def mainloop(self, display_banner=False):
152 while True:
153 try:
154 self.interact(display_banner=display_banner)
155 #self.interact_with_readline()
156 # XXX for testing of a readline-decoupled repl loop, call
157 # interact_with_readline above
158 break
159 except KeyboardInterrupt:
160 # this should not be necessary, but KeyboardInterrupt
161 # handling seems rather unpredictable...
162 self.write("\nKeyboardInterrupt in interact()\n")
163
164 def interact(self, display_banner=None):
165 """Closely emulate the interactive Python console."""
166
167 # batch run -> do not interact
168 if self.exit_now:
169 return
170
171 if display_banner is None:
172 display_banner = self.display_banner
173
174 if isinstance(display_banner, basestring):
175 self.show_banner(display_banner)
176 elif display_banner:
177 self.show_banner()
178
179 more = False
180
181 if self.has_readline:
182 self.readline_startup_hook(self.pre_readline)
183 # exit_now is set by a call to %Exit or %Quit, through the
184 # ask_exit callback.
185
186 while not self.exit_now:
187 if not self.km.is_alive:
188 ans = self.raw_input("kernel died, restart (y/n)?")
189 if not ans.lower().startswith('n'):
190 self.km.restart_kernel(True)
191 else:
192 self.exit_now=True
193 continue
194 self.hooks.pre_prompt_hook()
195 if more:
196 try:
197 prompt = self.hooks.generate_prompt(True)
198 except:
199 self.showtraceback()
200 if self.autoindent:
201 self.rl_do_indent = True
202
203 else:
204 try:
205 prompt = self.hooks.generate_prompt(False)
206 except:
207 self.showtraceback()
208 try:
209 line = self.raw_input(prompt)
210 if self.exit_now:
211 # quick exit on sys.std[in|out] close
212 break
213 if self.autoindent:
214 self.rl_do_indent = False
215
216 except KeyboardInterrupt:
217 #double-guard against keyboardinterrupts during kbdint handling
218 try:
219 self.write('\nKeyboardInterrupt\n')
220 self.input_splitter.reset()
221 more = False
222 except KeyboardInterrupt:
223 pass
224 except EOFError:
225 if self.autoindent:
226 self.rl_do_indent = False
227 if self.has_readline:
228 self.readline_startup_hook(None)
229 self.write('\n')
230 self.exit()
231 except bdb.BdbQuit:
232 warn('The Python debugger has exited with a BdbQuit exception.\n'
233 'Because of how pdb handles the stack, it is impossible\n'
234 'for IPython to properly format this particular exception.\n'
235 'IPython will resume normal operation.')
236 except:
237 # exceptions here are VERY RARE, but they can be triggered
238 # asynchronously by signal handlers, for example.
239 self.showtraceback()
240 else:
241 self.input_splitter.push(line)
242 more = self.input_splitter.push_accepts_more()
243 if (self.SyntaxTB.last_syntax_error and
244 self.autoedit_syntax):
245 self.edit_syntax_error()
246 if not more:
247 source_raw = self.input_splitter.source_reset()
248 self.run_cell(source_raw)
249
250
251 # Turn off the exit flag, so the mainloop can be restarted if desired
252 self.exit_now = False
@@ -1,399 +1,402 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.prompts import PromptManager
41 from IPython.core.prompts import PromptManager
42 from IPython.core.application import (
42 from IPython.core.application import (
43 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
43 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
44 )
44 )
45 from IPython.core.shellapp import (
45 from IPython.core.shellapp import (
46 InteractiveShellApp, shell_flags, shell_aliases
46 InteractiveShellApp, shell_flags, shell_aliases
47 )
47 )
48 from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
48 from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
49 from IPython.lib import inputhook
49 from IPython.lib import inputhook
50 from IPython.utils import warn
50 from IPython.utils import warn
51 from IPython.utils.path import get_ipython_dir, check_for_old_config
51 from IPython.utils.path import get_ipython_dir, check_for_old_config
52 from IPython.utils.traitlets import (
52 from IPython.utils.traitlets import (
53 Bool, List, Dict, CaselessStrEnum
53 Bool, List, Dict, CaselessStrEnum
54 )
54 )
55
55
56 #-----------------------------------------------------------------------------
56 #-----------------------------------------------------------------------------
57 # Globals, utilities and helpers
57 # Globals, utilities and helpers
58 #-----------------------------------------------------------------------------
58 #-----------------------------------------------------------------------------
59
59
60 #: The default config file name for this application.
60 #: The default config file name for this application.
61 default_config_file_name = u'ipython_config.py'
61 default_config_file_name = u'ipython_config.py'
62
62
63 _examples = """
63 _examples = """
64 ipython --pylab # start in pylab mode
64 ipython --pylab # start in pylab mode
65 ipython --pylab=qt # start in pylab mode with the qt4 backend
65 ipython --pylab=qt # start in pylab mode with the qt4 backend
66 ipython --log-level=DEBUG # set logging to DEBUG
66 ipython --log-level=DEBUG # set logging to DEBUG
67 ipython --profile=foo # start with profile foo
67 ipython --profile=foo # start with profile foo
68
68
69 ipython qtconsole # start the qtconsole GUI application
69 ipython qtconsole # start the qtconsole GUI application
70 ipython qtconsole -h # show the help string for the qtconsole subcmd
70 ipython qtconsole -h # show the help string for the qtconsole subcmd
71
71
72 ipython profile create foo # create profile foo w/ default config files
72 ipython profile create foo # create profile foo w/ default config files
73 ipython profile -h # show the help string for the profile subcmd
73 ipython profile -h # show the help string for the profile subcmd
74 """
74 """
75
75
76 #-----------------------------------------------------------------------------
76 #-----------------------------------------------------------------------------
77 # Crash handler for this application
77 # Crash handler for this application
78 #-----------------------------------------------------------------------------
78 #-----------------------------------------------------------------------------
79
79
80 class IPAppCrashHandler(CrashHandler):
80 class IPAppCrashHandler(CrashHandler):
81 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
81 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
82
82
83 def __init__(self, app):
83 def __init__(self, app):
84 contact_name = release.authors['Fernando'][0]
84 contact_name = release.authors['Fernando'][0]
85 contact_email = release.author_email
85 contact_email = release.author_email
86 bug_tracker = 'https://github.com/ipython/ipython/issues'
86 bug_tracker = 'https://github.com/ipython/ipython/issues'
87 super(IPAppCrashHandler,self).__init__(
87 super(IPAppCrashHandler,self).__init__(
88 app, contact_name, contact_email, bug_tracker
88 app, contact_name, contact_email, bug_tracker
89 )
89 )
90
90
91 def make_report(self,traceback):
91 def make_report(self,traceback):
92 """Return a string containing a crash report."""
92 """Return a string containing a crash report."""
93
93
94 sec_sep = self.section_sep
94 sec_sep = self.section_sep
95 # Start with parent report
95 # Start with parent report
96 report = [super(IPAppCrashHandler, self).make_report(traceback)]
96 report = [super(IPAppCrashHandler, self).make_report(traceback)]
97 # Add interactive-specific info we may have
97 # Add interactive-specific info we may have
98 rpt_add = report.append
98 rpt_add = report.append
99 try:
99 try:
100 rpt_add(sec_sep+"History of session input:")
100 rpt_add(sec_sep+"History of session input:")
101 for line in self.app.shell.user_ns['_ih']:
101 for line in self.app.shell.user_ns['_ih']:
102 rpt_add(line)
102 rpt_add(line)
103 rpt_add('\n*** Last line of input (may not be in above history):\n')
103 rpt_add('\n*** Last line of input (may not be in above history):\n')
104 rpt_add(self.app.shell._last_input_line+'\n')
104 rpt_add(self.app.shell._last_input_line+'\n')
105 except:
105 except:
106 pass
106 pass
107
107
108 return ''.join(report)
108 return ''.join(report)
109
109
110 #-----------------------------------------------------------------------------
110 #-----------------------------------------------------------------------------
111 # Aliases and Flags
111 # Aliases and Flags
112 #-----------------------------------------------------------------------------
112 #-----------------------------------------------------------------------------
113 flags = dict(base_flags)
113 flags = dict(base_flags)
114 flags.update(shell_flags)
114 flags.update(shell_flags)
115 addflag = lambda *args: flags.update(boolean_flag(*args))
115 addflag = lambda *args: flags.update(boolean_flag(*args))
116 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
116 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
117 'Turn on auto editing of files with syntax errors.',
117 'Turn on auto editing of files with syntax errors.',
118 'Turn off auto editing of files with syntax errors.'
118 'Turn off auto editing of files with syntax errors.'
119 )
119 )
120 addflag('banner', 'TerminalIPythonApp.display_banner',
120 addflag('banner', 'TerminalIPythonApp.display_banner',
121 "Display a banner upon starting IPython.",
121 "Display a banner upon starting IPython.",
122 "Don't display a banner upon starting IPython."
122 "Don't display a banner upon starting IPython."
123 )
123 )
124 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
124 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
125 """Set to confirm when you try to exit IPython with an EOF (Control-D
125 """Set to confirm when you try to exit IPython with an EOF (Control-D
126 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
126 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
127 you can force a direct exit without any confirmation.""",
127 you can force a direct exit without any confirmation.""",
128 "Don't prompt the user when exiting."
128 "Don't prompt the user when exiting."
129 )
129 )
130 addflag('term-title', 'TerminalInteractiveShell.term_title',
130 addflag('term-title', 'TerminalInteractiveShell.term_title',
131 "Enable auto setting the terminal title.",
131 "Enable auto setting the terminal title.",
132 "Disable auto setting the terminal title."
132 "Disable auto setting the terminal title."
133 )
133 )
134 classic_config = Config()
134 classic_config = Config()
135 classic_config.InteractiveShell.cache_size = 0
135 classic_config.InteractiveShell.cache_size = 0
136 classic_config.PlainTextFormatter.pprint = False
136 classic_config.PlainTextFormatter.pprint = False
137 classic_config.PromptManager.in_template = '>>> '
137 classic_config.PromptManager.in_template = '>>> '
138 classic_config.PromptManager.in2_template = '... '
138 classic_config.PromptManager.in2_template = '... '
139 classic_config.PromptManager.out_template = ''
139 classic_config.PromptManager.out_template = ''
140 classic_config.InteractiveShell.separate_in = ''
140 classic_config.InteractiveShell.separate_in = ''
141 classic_config.InteractiveShell.separate_out = ''
141 classic_config.InteractiveShell.separate_out = ''
142 classic_config.InteractiveShell.separate_out2 = ''
142 classic_config.InteractiveShell.separate_out2 = ''
143 classic_config.InteractiveShell.colors = 'NoColor'
143 classic_config.InteractiveShell.colors = 'NoColor'
144 classic_config.InteractiveShell.xmode = 'Plain'
144 classic_config.InteractiveShell.xmode = 'Plain'
145
145
146 flags['classic']=(
146 flags['classic']=(
147 classic_config,
147 classic_config,
148 "Gives IPython a similar feel to the classic Python prompt."
148 "Gives IPython a similar feel to the classic Python prompt."
149 )
149 )
150 # # log doesn't make so much sense this way anymore
150 # # log doesn't make so much sense this way anymore
151 # paa('--log','-l',
151 # paa('--log','-l',
152 # action='store_true', dest='InteractiveShell.logstart',
152 # action='store_true', dest='InteractiveShell.logstart',
153 # help="Start logging to the default log file (./ipython_log.py).")
153 # help="Start logging to the default log file (./ipython_log.py).")
154 #
154 #
155 # # quick is harder to implement
155 # # quick is harder to implement
156 flags['quick']=(
156 flags['quick']=(
157 {'TerminalIPythonApp' : {'quick' : True}},
157 {'TerminalIPythonApp' : {'quick' : True}},
158 "Enable quick startup with no config files."
158 "Enable quick startup with no config files."
159 )
159 )
160
160
161 flags['i'] = (
161 flags['i'] = (
162 {'TerminalIPythonApp' : {'force_interact' : True}},
162 {'TerminalIPythonApp' : {'force_interact' : True}},
163 """If running code from the command line, become interactive afterwards.
163 """If running code from the command line, become interactive afterwards.
164 Note: can also be given simply as '-i.'"""
164 Note: can also be given simply as '-i.'"""
165 )
165 )
166 flags['pylab'] = (
166 flags['pylab'] = (
167 {'TerminalIPythonApp' : {'pylab' : 'auto'}},
167 {'TerminalIPythonApp' : {'pylab' : 'auto'}},
168 """Pre-load matplotlib and numpy for interactive use with
168 """Pre-load matplotlib and numpy for interactive use with
169 the default matplotlib backend."""
169 the default matplotlib backend."""
170 )
170 )
171
171
172 aliases = dict(base_aliases)
172 aliases = dict(base_aliases)
173 aliases.update(shell_aliases)
173 aliases.update(shell_aliases)
174
174
175 # it's possible we don't want short aliases for *all* of these:
175 # it's possible we don't want short aliases for *all* of these:
176 aliases.update(dict(
176 aliases.update(dict(
177 gui='TerminalIPythonApp.gui',
177 gui='TerminalIPythonApp.gui',
178 pylab='TerminalIPythonApp.pylab',
178 pylab='TerminalIPythonApp.pylab',
179 ))
179 ))
180
180
181 #-----------------------------------------------------------------------------
181 #-----------------------------------------------------------------------------
182 # Main classes and functions
182 # Main classes and functions
183 #-----------------------------------------------------------------------------
183 #-----------------------------------------------------------------------------
184
184
185 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
185 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
186 name = u'ipython'
186 name = u'ipython'
187 description = usage.cl_usage
187 description = usage.cl_usage
188 default_config_file_name = default_config_file_name
188 default_config_file_name = default_config_file_name
189 crash_handler_class = IPAppCrashHandler
189 crash_handler_class = IPAppCrashHandler
190 examples = _examples
190 examples = _examples
191
191
192 flags = Dict(flags)
192 flags = Dict(flags)
193 aliases = Dict(aliases)
193 aliases = Dict(aliases)
194 classes = List()
194 classes = List()
195 def _classes_default(self):
195 def _classes_default(self):
196 """This has to be in a method, for TerminalIPythonApp to be available."""
196 """This has to be in a method, for TerminalIPythonApp to be available."""
197 return [
197 return [
198 InteractiveShellApp, # ShellApp comes before TerminalApp, because
198 InteractiveShellApp, # ShellApp comes before TerminalApp, because
199 self.__class__, # it will also affect subclasses (e.g. QtConsole)
199 self.__class__, # it will also affect subclasses (e.g. QtConsole)
200 TerminalInteractiveShell,
200 TerminalInteractiveShell,
201 PromptManager,
201 PromptManager,
202 ProfileDir,
202 ProfileDir,
203 PlainTextFormatter,
203 PlainTextFormatter,
204 IPCompleter,
204 IPCompleter,
205 ]
205 ]
206
206
207 subcommands = Dict(dict(
207 subcommands = Dict(dict(
208 qtconsole=('IPython.frontend.qt.console.qtconsoleapp.IPythonQtConsoleApp',
208 qtconsole=('IPython.frontend.qt.console.qtconsoleapp.IPythonQtConsoleApp',
209 """Launch the IPython Qt Console."""
209 """Launch the IPython Qt Console."""
210 ),
210 ),
211 notebook=('IPython.frontend.html.notebook.notebookapp.NotebookApp',
211 notebook=('IPython.frontend.html.notebook.notebookapp.NotebookApp',
212 """Launch the IPython HTML Notebook Server"""
212 """Launch the IPython HTML Notebook Server"""
213 ),
213 ),
214 profile = ("IPython.core.profileapp.ProfileApp",
214 profile = ("IPython.core.profileapp.ProfileApp",
215 "Create and manage IPython profiles."
215 "Create and manage IPython profiles."
216 ),
216 ),
217 kernel = ("IPython.zmq.ipkernel.IPKernelApp",
217 kernel = ("IPython.zmq.ipkernel.IPKernelApp",
218 "Start a kernel without an attached frontend."
218 "Start a kernel without an attached frontend."
219 ),
219 ),
220 zmq=('IPython.frontend.zmqterminal.app.ZMQTerminalIPythonApp',
221 """Launch two-process Terminal session with 0MQ."""
222 ),
220 ))
223 ))
221
224
222 # *do* autocreate requested profile, but don't create the config file.
225 # *do* autocreate requested profile, but don't create the config file.
223 auto_create=Bool(True)
226 auto_create=Bool(True)
224 # configurables
227 # configurables
225 ignore_old_config=Bool(False, config=True,
228 ignore_old_config=Bool(False, config=True,
226 help="Suppress warning messages about legacy config files"
229 help="Suppress warning messages about legacy config files"
227 )
230 )
228 quick = Bool(False, config=True,
231 quick = Bool(False, config=True,
229 help="""Start IPython quickly by skipping the loading of config files."""
232 help="""Start IPython quickly by skipping the loading of config files."""
230 )
233 )
231 def _quick_changed(self, name, old, new):
234 def _quick_changed(self, name, old, new):
232 if new:
235 if new:
233 self.load_config_file = lambda *a, **kw: None
236 self.load_config_file = lambda *a, **kw: None
234 self.ignore_old_config=True
237 self.ignore_old_config=True
235
238
236 gui = CaselessStrEnum(('qt', 'wx', 'gtk', 'glut', 'pyglet'), config=True,
239 gui = CaselessStrEnum(('qt', 'wx', 'gtk', 'glut', 'pyglet'), config=True,
237 help="Enable GUI event loop integration ('qt', 'wx', 'gtk', 'glut', 'pyglet')."
240 help="Enable GUI event loop integration ('qt', 'wx', 'gtk', 'glut', 'pyglet')."
238 )
241 )
239 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'auto'],
242 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'auto'],
240 config=True,
243 config=True,
241 help="""Pre-load matplotlib and numpy for interactive use,
244 help="""Pre-load matplotlib and numpy for interactive use,
242 selecting a particular matplotlib backend and loop integration.
245 selecting a particular matplotlib backend and loop integration.
243 """
246 """
244 )
247 )
245 display_banner = Bool(True, config=True,
248 display_banner = Bool(True, config=True,
246 help="Whether to display a banner upon starting IPython."
249 help="Whether to display a banner upon starting IPython."
247 )
250 )
248
251
249 # if there is code of files to run from the cmd line, don't interact
252 # if there is code of files to run from the cmd line, don't interact
250 # unless the --i flag (App.force_interact) is true.
253 # unless the --i flag (App.force_interact) is true.
251 force_interact = Bool(False, config=True,
254 force_interact = Bool(False, config=True,
252 help="""If a command or file is given via the command-line,
255 help="""If a command or file is given via the command-line,
253 e.g. 'ipython foo.py"""
256 e.g. 'ipython foo.py"""
254 )
257 )
255 def _force_interact_changed(self, name, old, new):
258 def _force_interact_changed(self, name, old, new):
256 if new:
259 if new:
257 self.interact = True
260 self.interact = True
258
261
259 def _file_to_run_changed(self, name, old, new):
262 def _file_to_run_changed(self, name, old, new):
260 if new and not self.force_interact:
263 if new and not self.force_interact:
261 self.interact = False
264 self.interact = False
262 _code_to_run_changed = _file_to_run_changed
265 _code_to_run_changed = _file_to_run_changed
263
266
264 # internal, not-configurable
267 # internal, not-configurable
265 interact=Bool(True)
268 interact=Bool(True)
266
269
267
270
268 def parse_command_line(self, argv=None):
271 def parse_command_line(self, argv=None):
269 """override to allow old '-pylab' flag with deprecation warning"""
272 """override to allow old '-pylab' flag with deprecation warning"""
270
273
271 argv = sys.argv[1:] if argv is None else argv
274 argv = sys.argv[1:] if argv is None else argv
272
275
273 if '-pylab' in argv:
276 if '-pylab' in argv:
274 # deprecated `-pylab` given,
277 # deprecated `-pylab` given,
275 # warn and transform into current syntax
278 # warn and transform into current syntax
276 argv = argv[:] # copy, don't clobber
279 argv = argv[:] # copy, don't clobber
277 idx = argv.index('-pylab')
280 idx = argv.index('-pylab')
278 warn.warn("`-pylab` flag has been deprecated.\n"
281 warn.warn("`-pylab` flag has been deprecated.\n"
279 " Use `--pylab` instead, or `--pylab=foo` to specify a backend.")
282 " Use `--pylab` instead, or `--pylab=foo` to specify a backend.")
280 sub = '--pylab'
283 sub = '--pylab'
281 if len(argv) > idx+1:
284 if len(argv) > idx+1:
282 # check for gui arg, as in '-pylab qt'
285 # check for gui arg, as in '-pylab qt'
283 gui = argv[idx+1]
286 gui = argv[idx+1]
284 if gui in ('wx', 'qt', 'qt4', 'gtk', 'auto'):
287 if gui in ('wx', 'qt', 'qt4', 'gtk', 'auto'):
285 sub = '--pylab='+gui
288 sub = '--pylab='+gui
286 argv.pop(idx+1)
289 argv.pop(idx+1)
287 argv[idx] = sub
290 argv[idx] = sub
288
291
289 return super(TerminalIPythonApp, self).parse_command_line(argv)
292 return super(TerminalIPythonApp, self).parse_command_line(argv)
290
293
291 @catch_config_error
294 @catch_config_error
292 def initialize(self, argv=None):
295 def initialize(self, argv=None):
293 """Do actions after construct, but before starting the app."""
296 """Do actions after construct, but before starting the app."""
294 super(TerminalIPythonApp, self).initialize(argv)
297 super(TerminalIPythonApp, self).initialize(argv)
295 if self.subapp is not None:
298 if self.subapp is not None:
296 # don't bother initializing further, starting subapp
299 # don't bother initializing further, starting subapp
297 return
300 return
298 if not self.ignore_old_config:
301 if not self.ignore_old_config:
299 check_for_old_config(self.ipython_dir)
302 check_for_old_config(self.ipython_dir)
300 # print self.extra_args
303 # print self.extra_args
301 if self.extra_args:
304 if self.extra_args:
302 self.file_to_run = self.extra_args[0]
305 self.file_to_run = self.extra_args[0]
303 # create the shell
306 # create the shell
304 self.init_shell()
307 self.init_shell()
305 # and draw the banner
308 # and draw the banner
306 self.init_banner()
309 self.init_banner()
307 # Now a variety of things that happen after the banner is printed.
310 # Now a variety of things that happen after the banner is printed.
308 self.init_gui_pylab()
311 self.init_gui_pylab()
309 self.init_extensions()
312 self.init_extensions()
310 self.init_code()
313 self.init_code()
311
314
312 def init_shell(self):
315 def init_shell(self):
313 """initialize the InteractiveShell instance"""
316 """initialize the InteractiveShell instance"""
314 # I am a little hesitant to put these into InteractiveShell itself.
317 # I am a little hesitant to put these into InteractiveShell itself.
315 # But that might be the place for them
318 # But that might be the place for them
316 sys.path.insert(0, '')
319 sys.path.insert(0, '')
317
320
318 # Create an InteractiveShell instance.
321 # Create an InteractiveShell instance.
319 # shell.display_banner should always be False for the terminal
322 # shell.display_banner should always be False for the terminal
320 # based app, because we call shell.show_banner() by hand below
323 # based app, because we call shell.show_banner() by hand below
321 # so the banner shows *before* all extension loading stuff.
324 # so the banner shows *before* all extension loading stuff.
322 self.shell = TerminalInteractiveShell.instance(config=self.config,
325 self.shell = TerminalInteractiveShell.instance(config=self.config,
323 display_banner=False, profile_dir=self.profile_dir,
326 display_banner=False, profile_dir=self.profile_dir,
324 ipython_dir=self.ipython_dir)
327 ipython_dir=self.ipython_dir)
325 self.shell.configurables.append(self)
328 self.shell.configurables.append(self)
326
329
327 def init_banner(self):
330 def init_banner(self):
328 """optionally display the banner"""
331 """optionally display the banner"""
329 if self.display_banner and self.interact:
332 if self.display_banner and self.interact:
330 self.shell.show_banner()
333 self.shell.show_banner()
331 # Make sure there is a space below the banner.
334 # Make sure there is a space below the banner.
332 if self.log_level <= logging.INFO: print
335 if self.log_level <= logging.INFO: print
333
336
334
337
335 def init_gui_pylab(self):
338 def init_gui_pylab(self):
336 """Enable GUI event loop integration, taking pylab into account."""
339 """Enable GUI event loop integration, taking pylab into account."""
337 gui = self.gui
340 gui = self.gui
338
341
339 # Using `pylab` will also require gui activation, though which toolkit
342 # Using `pylab` will also require gui activation, though which toolkit
340 # to use may be chosen automatically based on mpl configuration.
343 # to use may be chosen automatically based on mpl configuration.
341 if self.pylab:
344 if self.pylab:
342 activate = self.shell.enable_pylab
345 activate = self.shell.enable_pylab
343 if self.pylab == 'auto':
346 if self.pylab == 'auto':
344 gui = None
347 gui = None
345 else:
348 else:
346 gui = self.pylab
349 gui = self.pylab
347 else:
350 else:
348 # Enable only GUI integration, no pylab
351 # Enable only GUI integration, no pylab
349 activate = inputhook.enable_gui
352 activate = inputhook.enable_gui
350
353
351 if gui or self.pylab:
354 if gui or self.pylab:
352 try:
355 try:
353 self.log.info("Enabling GUI event loop integration, "
356 self.log.info("Enabling GUI event loop integration, "
354 "toolkit=%s, pylab=%s" % (gui, self.pylab) )
357 "toolkit=%s, pylab=%s" % (gui, self.pylab) )
355 if self.pylab:
358 if self.pylab:
356 activate(gui, import_all=self.pylab_import_all)
359 activate(gui, import_all=self.pylab_import_all)
357 else:
360 else:
358 activate(gui)
361 activate(gui)
359 except:
362 except:
360 self.log.warn("Error in enabling GUI event loop integration:")
363 self.log.warn("Error in enabling GUI event loop integration:")
361 self.shell.showtraceback()
364 self.shell.showtraceback()
362
365
363 def start(self):
366 def start(self):
364 if self.subapp is not None:
367 if self.subapp is not None:
365 return self.subapp.start()
368 return self.subapp.start()
366 # perform any prexec steps:
369 # perform any prexec steps:
367 if self.interact:
370 if self.interact:
368 self.log.debug("Starting IPython's mainloop...")
371 self.log.debug("Starting IPython's mainloop...")
369 self.shell.mainloop()
372 self.shell.mainloop()
370 else:
373 else:
371 self.log.debug("IPython not interactive...")
374 self.log.debug("IPython not interactive...")
372
375
373
376
374 def load_default_config(ipython_dir=None):
377 def load_default_config(ipython_dir=None):
375 """Load the default config file from the default ipython_dir.
378 """Load the default config file from the default ipython_dir.
376
379
377 This is useful for embedded shells.
380 This is useful for embedded shells.
378 """
381 """
379 if ipython_dir is None:
382 if ipython_dir is None:
380 ipython_dir = get_ipython_dir()
383 ipython_dir = get_ipython_dir()
381 profile_dir = os.path.join(ipython_dir, 'profile_default')
384 profile_dir = os.path.join(ipython_dir, 'profile_default')
382 cl = PyFileConfigLoader(default_config_file_name, profile_dir)
385 cl = PyFileConfigLoader(default_config_file_name, profile_dir)
383 try:
386 try:
384 config = cl.load_config()
387 config = cl.load_config()
385 except ConfigFileNotFound:
388 except ConfigFileNotFound:
386 # no config found
389 # no config found
387 config = Config()
390 config = Config()
388 return config
391 return config
389
392
390
393
391 def launch_new_instance():
394 def launch_new_instance():
392 """Create and run a full blown IPython instance"""
395 """Create and run a full blown IPython instance"""
393 app = TerminalIPythonApp.instance()
396 app = TerminalIPythonApp.instance()
394 app.initialize()
397 app.initialize()
395 app.start()
398 app.start()
396
399
397
400
398 if __name__ == '__main__':
401 if __name__ == '__main__':
399 launch_new_instance()
402 launch_new_instance()
@@ -1,41 +1,44 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 import readline
2 import readline
3 from Queue import Empty
3 from Queue import Empty
4
4
5 class ClientCompleter2p(object):
5 class ZMQCompleter(object):
6 """Client-side completion machinery.
6 """Client-side completion machinery.
7
7
8 How it works: self.complete will be called multiple times, with
8 How it works: self.complete will be called multiple times, with
9 state=0,1,2,... When state=0 it should compute ALL the completion matches,
9 state=0,1,2,... When state=0 it should compute ALL the completion matches,
10 and then return them for each value of state."""
10 and then return them for each value of state."""
11
11
12 def __init__(self,client, km):
12 def __init__(self, shell, km):
13 self.shell = shell
13 self.km = km
14 self.km = km
14 self.matches = []
15 self.matches = []
15 self.client = client
16
16
17 def complete_request(self,text):
17 def complete_request(self,text):
18 line = readline.get_line_buffer()
18 line = readline.get_line_buffer()
19 cursor_pos = readline.get_endidx()
19 cursor_pos = readline.get_endidx()
20
20
21 # send completion request to kernel
21 # send completion request to kernel
22 # Give the kernel up to 0.5s to respond
22 # Give the kernel up to 0.5s to respond
23 msg_id = self.km.xreq_channel.complete(text=text, line=line,
23 msg_id = self.km.shell_channel.complete(text=text, line=line,
24 cursor_pos=cursor_pos)
24 cursor_pos=cursor_pos)
25
25
26 msg_xreq = self.km.xreq_channel.get_msg(timeout=0.5)
26 msg = self.km.shell_channel.get_msg(timeout=0.5)
27 if msg_xreq['parent_header']['msg_id'] == msg_id:
27 if msg['parent_header']['msg_id'] == msg_id:
28 return msg_xreq["content"]["matches"]
28 return msg["content"]["matches"]
29 return []
29 return []
30
30
31 def complete(self, text, state):
31 def rlcomplete(self, text, state):
32 if state == 0:
32 if state == 0:
33 try:
33 try:
34 self.matches = self.complete_request(text)
34 self.matches = self.complete_request(text)
35 except Empty:
35 except Empty:
36 print('WARNING: Kernel timeout on tab completion.')
36 print('WARNING: Kernel timeout on tab completion.')
37
37
38 try:
38 try:
39 return self.matches[state]
39 return self.matches[state]
40 except IndexError:
40 except IndexError:
41 return None
41 return None
42
43 def complete(self, text, line, cursor_pos=None):
44 return self.rlcomplete(text, 0)
General Comments 0
You need to be logged in to leave comments. Login now