##// END OF EJS Templates
Don't blend kernel and frontend CLI args...
Min RK -
Show More
@@ -1,344 +1,330 b''
1 1 """ A minimal application base mixin for all ZMQ based IPython frontends.
2 2
3 3 This is not a complete console app, as subprocess will not be able to receive
4 4 input, there is no real readline support, among other limitations. This is a
5 5 refactoring of what used to be the IPython/qt/console/qtconsoleapp.py
6 6 """
7 7 # Copyright (c) IPython Development Team.
8 8 # Distributed under the terms of the Modified BSD License.
9 9
10 10 import atexit
11 11 import os
12 12 import signal
13 13 import sys
14 14 import uuid
15 15
16 16
17 17 from IPython.config.application import boolean_flag
18 18 from IPython.core.profiledir import ProfileDir
19 19 from IPython.kernel.blocking import BlockingKernelClient
20 20 from IPython.kernel import KernelManager
21 from IPython.kernel import tunnel_to_kernel, find_connection_file, swallow_argv
21 from IPython.kernel import tunnel_to_kernel, find_connection_file
22 22 from IPython.kernel.kernelspec import NoSuchKernel
23 23 from IPython.utils.path import filefind
24 24 from IPython.utils.traitlets import (
25 25 Dict, List, Unicode, CUnicode, CBool, Any
26 26 )
27 from IPython.kernel.zmq.kernelapp import (
28 kernel_flags,
29 kernel_aliases,
30 IPKernelApp
31 )
32 from IPython.kernel.zmq.pylab.config import InlineBackend
33 27 from IPython.kernel.zmq.session import Session
34 from IPython.kernel.zmq.zmqshell import ZMQInteractiveShell
35 28 from IPython.kernel.connect import ConnectionFileMixin
36 29
37 30 from IPython.utils.localinterfaces import localhost
38 31
39 32 #-----------------------------------------------------------------------------
40 33 # Aliases and Flags
41 34 #-----------------------------------------------------------------------------
42 35
43 flags = dict(kernel_flags)
36 flags = {}
44 37
45 38 # the flags that are specific to the frontend
46 39 # these must be scrubbed before being passed to the kernel,
47 40 # or it will raise an error on unrecognized flags
48 41 app_flags = {
49 42 'existing' : ({'IPythonConsoleApp' : {'existing' : 'kernel*.json'}},
50 43 "Connect to an existing kernel. If no argument specified, guess most recent"),
51 44 }
52 45 app_flags.update(boolean_flag(
53 46 'confirm-exit', 'IPythonConsoleApp.confirm_exit',
54 47 """Set to display confirmation dialog on exit. You can always use 'exit' or 'quit',
55 48 to force a direct exit without any confirmation.
56 49 """,
57 50 """Don't prompt the user when exiting. This will terminate the kernel
58 51 if it is owned by the frontend, and leave it alive if it is external.
59 52 """
60 53 ))
61 54 flags.update(app_flags)
62 55
63 aliases = dict(kernel_aliases)
56 aliases = {}
64 57
65 58 # also scrub aliases from the frontend
66 59 app_aliases = dict(
67 60 ip = 'IPythonConsoleApp.ip',
68 61 transport = 'IPythonConsoleApp.transport',
69 62 hb = 'IPythonConsoleApp.hb_port',
70 63 shell = 'IPythonConsoleApp.shell_port',
71 64 iopub = 'IPythonConsoleApp.iopub_port',
72 65 stdin = 'IPythonConsoleApp.stdin_port',
73 66 existing = 'IPythonConsoleApp.existing',
74 67 f = 'IPythonConsoleApp.connection_file',
75 68
76 69 kernel = 'IPythonConsoleApp.kernel_name',
77 70
78 71 ssh = 'IPythonConsoleApp.sshserver',
79 72 )
80 73 aliases.update(app_aliases)
81 74
82 75 #-----------------------------------------------------------------------------
83 76 # Classes
84 77 #-----------------------------------------------------------------------------
85 78
86 79 classes = [KernelManager, ProfileDir, Session]
87 80
88 81 class IPythonConsoleApp(ConnectionFileMixin):
89 82 name = 'ipython-console-mixin'
90 83
91 84 description = """
92 85 The IPython Mixin Console.
93 86
94 87 This class contains the common portions of console client (QtConsole,
95 88 ZMQ-based terminal console, etc). It is not a full console, in that
96 89 launched terminal subprocesses will not be able to accept input.
97 90
98 91 The Console using this mixing supports various extra features beyond
99 92 the single-process Terminal IPython shell, such as connecting to
100 93 existing kernel, via:
101 94
102 95 ipython <appname> --existing
103 96
104 97 as well as tunnel via SSH
105 98
106 99 """
107 100
108 101 classes = classes
109 102 flags = Dict(flags)
110 103 aliases = Dict(aliases)
111 104 kernel_manager_class = KernelManager
112 105 kernel_client_class = BlockingKernelClient
113 106
114 107 kernel_argv = List(Unicode)
115 108 # frontend flags&aliases to be stripped when building kernel_argv
116 109 frontend_flags = Any(app_flags)
117 110 frontend_aliases = Any(app_aliases)
118 111
119 112 # create requested profiles by default, if they don't exist:
120 113 auto_create = CBool(True)
121 114 # connection info:
122 115
123 116 sshserver = Unicode('', config=True,
124 117 help="""The SSH server to use to connect to the kernel.""")
125 118 sshkey = Unicode('', config=True,
126 119 help="""Path to the ssh key to use for logging in to the ssh server.""")
127 120
128 121 def _connection_file_default(self):
129 122 return 'kernel-%i.json' % os.getpid()
130 123
131 124 existing = CUnicode('', config=True,
132 125 help="""Connect to an already running kernel""")
133 126
134 127 kernel_name = Unicode('python', config=True,
135 128 help="""The name of the default kernel to start.""")
136 129
137 130 confirm_exit = CBool(True, config=True,
138 131 help="""
139 132 Set to display confirmation dialog on exit. You can always use 'exit' or 'quit',
140 133 to force a direct exit without any confirmation.""",
141 134 )
142 135
143 @property
144 def help_classes(self):
145 """ConsoleApps can configure kernels on the command-line
136 def build_kernel_argv(self, argv=None):
137 """build argv to be passed to kernel subprocess
146 138
147 But this shouldn't be written to a file
139 Override in subclasses if any args should be passed to the kernel
148 140 """
149 return self.classes + [IPKernelApp] + IPKernelApp.classes
150
151 def build_kernel_argv(self, argv=None):
152 """build argv to be passed to kernel subprocess"""
153 if argv is None:
154 argv = sys.argv[1:]
155 self.kernel_argv = swallow_argv(argv, self.frontend_aliases, self.frontend_flags)
141 self.kernel_argv = self.extra_args
156 142
157 143 def init_connection_file(self):
158 144 """find the connection file, and load the info if found.
159 145
160 146 The current working directory and the current profile's security
161 147 directory will be searched for the file if it is not given by
162 148 absolute path.
163 149
164 150 When attempting to connect to an existing kernel and the `--existing`
165 151 argument does not match an existing file, it will be interpreted as a
166 152 fileglob, and the matching file in the current profile's security dir
167 153 with the latest access time will be used.
168 154
169 155 After this method is called, self.connection_file contains the *full path*
170 156 to the connection file, never just its name.
171 157 """
172 158 if self.existing:
173 159 try:
174 160 cf = find_connection_file(self.existing)
175 161 except Exception:
176 162 self.log.critical("Could not find existing kernel connection file %s", self.existing)
177 163 self.exit(1)
178 164 self.log.debug("Connecting to existing kernel: %s" % cf)
179 165 self.connection_file = cf
180 166 else:
181 167 # not existing, check if we are going to write the file
182 168 # and ensure that self.connection_file is a full path, not just the shortname
183 169 try:
184 170 cf = find_connection_file(self.connection_file)
185 171 except Exception:
186 172 # file might not exist
187 173 if self.connection_file == os.path.basename(self.connection_file):
188 174 # just shortname, put it in security dir
189 175 cf = os.path.join(self.profile_dir.security_dir, self.connection_file)
190 176 else:
191 177 cf = self.connection_file
192 178 self.connection_file = cf
193 179 try:
194 180 self.connection_file = filefind(self.connection_file, ['.', self.profile_dir.security_dir])
195 181 except IOError:
196 182 self.log.debug("Connection File not found: %s", self.connection_file)
197 183 return
198 184
199 185 # should load_connection_file only be used for existing?
200 186 # as it is now, this allows reusing ports if an existing
201 187 # file is requested
202 188 try:
203 189 self.load_connection_file()
204 190 except Exception:
205 191 self.log.error("Failed to load connection file: %r", self.connection_file, exc_info=True)
206 192 self.exit(1)
207 193
208 194 def init_ssh(self):
209 195 """set up ssh tunnels, if needed."""
210 196 if not self.existing or (not self.sshserver and not self.sshkey):
211 197 return
212 198 self.load_connection_file()
213 199
214 200 transport = self.transport
215 201 ip = self.ip
216 202
217 203 if transport != 'tcp':
218 204 self.log.error("Can only use ssh tunnels with TCP sockets, not %s", transport)
219 205 sys.exit(-1)
220 206
221 207 if self.sshkey and not self.sshserver:
222 208 # specifying just the key implies that we are connecting directly
223 209 self.sshserver = ip
224 210 ip = localhost()
225 211
226 212 # build connection dict for tunnels:
227 213 info = dict(ip=ip,
228 214 shell_port=self.shell_port,
229 215 iopub_port=self.iopub_port,
230 216 stdin_port=self.stdin_port,
231 217 hb_port=self.hb_port
232 218 )
233 219
234 220 self.log.info("Forwarding connections to %s via %s"%(ip, self.sshserver))
235 221
236 222 # tunnels return a new set of ports, which will be on localhost:
237 223 self.ip = localhost()
238 224 try:
239 225 newports = tunnel_to_kernel(info, self.sshserver, self.sshkey)
240 226 except:
241 227 # even catch KeyboardInterrupt
242 228 self.log.error("Could not setup tunnels", exc_info=True)
243 229 self.exit(1)
244 230
245 231 self.shell_port, self.iopub_port, self.stdin_port, self.hb_port = newports
246 232
247 233 cf = self.connection_file
248 234 base,ext = os.path.splitext(cf)
249 235 base = os.path.basename(base)
250 236 self.connection_file = os.path.basename(base)+'-ssh'+ext
251 237 self.log.info("To connect another client via this tunnel, use:")
252 238 self.log.info("--existing %s" % self.connection_file)
253 239
254 240 def _new_connection_file(self):
255 241 cf = ''
256 242 while not cf:
257 243 # we don't need a 128b id to distinguish kernels, use more readable
258 244 # 48b node segment (12 hex chars). Users running more than 32k simultaneous
259 245 # kernels can subclass.
260 246 ident = str(uuid.uuid4()).split('-')[-1]
261 247 cf = os.path.join(self.profile_dir.security_dir, 'kernel-%s.json' % ident)
262 248 # only keep if it's actually new. Protect against unlikely collision
263 249 # in 48b random search space
264 250 cf = cf if not os.path.exists(cf) else ''
265 251 return cf
266 252
267 253 def init_kernel_manager(self):
268 254 # Don't let Qt or ZMQ swallow KeyboardInterupts.
269 255 if self.existing:
270 256 self.kernel_manager = None
271 257 return
272 258 signal.signal(signal.SIGINT, signal.SIG_DFL)
273 259
274 260 # Create a KernelManager and start a kernel.
275 261 try:
276 262 self.kernel_manager = self.kernel_manager_class(
277 263 ip=self.ip,
278 264 session=self.session,
279 265 transport=self.transport,
280 266 shell_port=self.shell_port,
281 267 iopub_port=self.iopub_port,
282 268 stdin_port=self.stdin_port,
283 269 hb_port=self.hb_port,
284 270 connection_file=self.connection_file,
285 271 kernel_name=self.kernel_name,
286 272 parent=self,
287 273 ipython_dir=self.ipython_dir,
288 274 )
289 275 except NoSuchKernel:
290 276 self.log.critical("Could not find kernel %s", self.kernel_name)
291 277 self.exit(1)
292 278
293 279 self.kernel_manager.client_factory = self.kernel_client_class
294 280 # FIXME: remove special treatment of IPython kernels
295 281 kwargs = {}
296 282 if self.kernel_manager.ipython_kernel:
297 283 kwargs['extra_arguments'] = self.kernel_argv
298 284 self.kernel_manager.start_kernel(**kwargs)
299 285 atexit.register(self.kernel_manager.cleanup_ipc_files)
300 286
301 287 if self.sshserver:
302 288 # ssh, write new connection file
303 289 self.kernel_manager.write_connection_file()
304 290
305 291 # in case KM defaults / ssh writing changes things:
306 292 km = self.kernel_manager
307 293 self.shell_port=km.shell_port
308 294 self.iopub_port=km.iopub_port
309 295 self.stdin_port=km.stdin_port
310 296 self.hb_port=km.hb_port
311 297 self.connection_file = km.connection_file
312 298
313 299 atexit.register(self.kernel_manager.cleanup_connection_file)
314 300
315 301 def init_kernel_client(self):
316 302 if self.kernel_manager is not None:
317 303 self.kernel_client = self.kernel_manager.client()
318 304 else:
319 305 self.kernel_client = self.kernel_client_class(
320 306 session=self.session,
321 307 ip=self.ip,
322 308 transport=self.transport,
323 309 shell_port=self.shell_port,
324 310 iopub_port=self.iopub_port,
325 311 stdin_port=self.stdin_port,
326 312 hb_port=self.hb_port,
327 313 connection_file=self.connection_file,
328 314 parent=self,
329 315 )
330 316
331 317 self.kernel_client.start_channels()
332 318
333 319
334 320
335 321 def initialize(self, argv=None):
336 322 """
337 323 Classes which mix this class in should call:
338 324 IPythonConsoleApp.initialize(self,argv)
339 325 """
340 326 self.init_connection_file()
341 327 self.init_ssh()
342 328 self.init_kernel_manager()
343 329 self.init_kernel_client()
344 330
@@ -1,395 +1,380 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 """
4 4 The :class:`~IPython.core.application.Application` object for the command
5 5 line :command:`ipython` program.
6
7 Authors
8 -------
9
10 * Brian Granger
11 * Fernando Perez
12 * Min Ragan-Kelley
13 6 """
14 7
15 #-----------------------------------------------------------------------------
16 # Copyright (C) 2008-2011 The IPython Development Team
17 #
18 # Distributed under the terms of the BSD License. The full license is in
19 # the file COPYING, distributed as part of this software.
20 #-----------------------------------------------------------------------------
21
22 #-----------------------------------------------------------------------------
23 # Imports
24 #-----------------------------------------------------------------------------
8 # Copyright (c) IPython Development Team.
9 # Distributed under the terms of the Modified BSD License.
25 10
26 11 from __future__ import absolute_import
27 12 from __future__ import print_function
28 13
29 14 import logging
30 15 import os
31 16 import sys
32 17
33 18 from IPython.config.loader import Config
34 19 from IPython.config.application import boolean_flag, catch_config_error, Application
35 20 from IPython.core import release
36 21 from IPython.core import usage
37 22 from IPython.core.completer import IPCompleter
38 23 from IPython.core.crashhandler import CrashHandler
39 24 from IPython.core.formatters import PlainTextFormatter
40 25 from IPython.core.history import HistoryManager
41 26 from IPython.core.prompts import PromptManager
42 27 from IPython.core.application import (
43 28 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
44 29 )
45 30 from IPython.core.magics import ScriptMagics
46 31 from IPython.core.shellapp import (
47 32 InteractiveShellApp, shell_flags, shell_aliases
48 33 )
49 34 from IPython.extensions.storemagic import StoreMagics
50 35 from IPython.terminal.interactiveshell import TerminalInteractiveShell
51 36 from IPython.utils import warn
52 37 from IPython.utils.path import get_ipython_dir, check_for_old_config
53 38 from IPython.utils.traitlets import (
54 39 Bool, List, Dict,
55 40 )
56 41
57 42 #-----------------------------------------------------------------------------
58 43 # Globals, utilities and helpers
59 44 #-----------------------------------------------------------------------------
60 45
61 46 _examples = """
62 47 ipython --matplotlib # enable matplotlib integration
63 48 ipython --matplotlib=qt # enable matplotlib integration with qt4 backend
64 49
65 50 ipython --log-level=DEBUG # set logging to DEBUG
66 51 ipython --profile=foo # start with profile foo
67 52
68 53 ipython qtconsole # start the qtconsole GUI application
69 54 ipython help qtconsole # show the help for the qtconsole subcmd
70 55
71 56 ipython console # start the terminal-based console application
72 57 ipython help console # show the help for the console subcmd
73 58
74 59 ipython notebook # start the IPython notebook
75 60 ipython help notebook # show the help for the notebook subcmd
76 61
77 62 ipython profile create foo # create profile foo w/ default config files
78 63 ipython help profile # show the help for the profile subcmd
79 64
80 65 ipython locate # print the path to the IPython directory
81 66 ipython locate profile foo # print the path to the directory for profile `foo`
82 67
83 68 ipython nbconvert # convert notebooks to/from other formats
84 69 """
85 70
86 71 #-----------------------------------------------------------------------------
87 72 # Crash handler for this application
88 73 #-----------------------------------------------------------------------------
89 74
90 75 class IPAppCrashHandler(CrashHandler):
91 76 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
92 77
93 78 def __init__(self, app):
94 79 contact_name = release.author
95 80 contact_email = release.author_email
96 81 bug_tracker = 'https://github.com/ipython/ipython/issues'
97 82 super(IPAppCrashHandler,self).__init__(
98 83 app, contact_name, contact_email, bug_tracker
99 84 )
100 85
101 86 def make_report(self,traceback):
102 87 """Return a string containing a crash report."""
103 88
104 89 sec_sep = self.section_sep
105 90 # Start with parent report
106 91 report = [super(IPAppCrashHandler, self).make_report(traceback)]
107 92 # Add interactive-specific info we may have
108 93 rpt_add = report.append
109 94 try:
110 95 rpt_add(sec_sep+"History of session input:")
111 96 for line in self.app.shell.user_ns['_ih']:
112 97 rpt_add(line)
113 98 rpt_add('\n*** Last line of input (may not be in above history):\n')
114 99 rpt_add(self.app.shell._last_input_line+'\n')
115 100 except:
116 101 pass
117 102
118 103 return ''.join(report)
119 104
120 105 #-----------------------------------------------------------------------------
121 106 # Aliases and Flags
122 107 #-----------------------------------------------------------------------------
123 108 flags = dict(base_flags)
124 109 flags.update(shell_flags)
125 110 frontend_flags = {}
126 111 addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
127 112 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
128 113 'Turn on auto editing of files with syntax errors.',
129 114 'Turn off auto editing of files with syntax errors.'
130 115 )
131 116 addflag('banner', 'TerminalIPythonApp.display_banner',
132 117 "Display a banner upon starting IPython.",
133 118 "Don't display a banner upon starting IPython."
134 119 )
135 120 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
136 121 """Set to confirm when you try to exit IPython with an EOF (Control-D
137 122 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
138 123 you can force a direct exit without any confirmation.""",
139 124 "Don't prompt the user when exiting."
140 125 )
141 126 addflag('term-title', 'TerminalInteractiveShell.term_title',
142 127 "Enable auto setting the terminal title.",
143 128 "Disable auto setting the terminal title."
144 129 )
145 130 classic_config = Config()
146 131 classic_config.InteractiveShell.cache_size = 0
147 132 classic_config.PlainTextFormatter.pprint = False
148 133 classic_config.PromptManager.in_template = '>>> '
149 134 classic_config.PromptManager.in2_template = '... '
150 135 classic_config.PromptManager.out_template = ''
151 136 classic_config.InteractiveShell.separate_in = ''
152 137 classic_config.InteractiveShell.separate_out = ''
153 138 classic_config.InteractiveShell.separate_out2 = ''
154 139 classic_config.InteractiveShell.colors = 'NoColor'
155 140 classic_config.InteractiveShell.xmode = 'Plain'
156 141
157 142 frontend_flags['classic']=(
158 143 classic_config,
159 144 "Gives IPython a similar feel to the classic Python prompt."
160 145 )
161 146 # # log doesn't make so much sense this way anymore
162 147 # paa('--log','-l',
163 148 # action='store_true', dest='InteractiveShell.logstart',
164 149 # help="Start logging to the default log file (./ipython_log.py).")
165 150 #
166 151 # # quick is harder to implement
167 152 frontend_flags['quick']=(
168 153 {'TerminalIPythonApp' : {'quick' : True}},
169 154 "Enable quick startup with no config files."
170 155 )
171 156
172 157 frontend_flags['i'] = (
173 158 {'TerminalIPythonApp' : {'force_interact' : True}},
174 159 """If running code from the command line, become interactive afterwards."""
175 160 )
176 161 flags.update(frontend_flags)
177 162
178 163 aliases = dict(base_aliases)
179 164 aliases.update(shell_aliases)
180 165
181 166 #-----------------------------------------------------------------------------
182 167 # Main classes and functions
183 168 #-----------------------------------------------------------------------------
184 169
185 170
186 171 class LocateIPythonApp(BaseIPythonApplication):
187 172 description = """print the path to the IPython dir"""
188 173 subcommands = Dict(dict(
189 174 profile=('IPython.core.profileapp.ProfileLocate',
190 175 "print the path to an IPython profile directory",
191 176 ),
192 177 ))
193 178 def start(self):
194 179 if self.subapp is not None:
195 180 return self.subapp.start()
196 181 else:
197 182 print(self.ipython_dir)
198 183
199 184
200 185 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
201 186 name = u'ipython'
202 187 description = usage.cl_usage
203 188 crash_handler_class = IPAppCrashHandler
204 189 examples = _examples
205 190
206 191 flags = Dict(flags)
207 192 aliases = Dict(aliases)
208 193 classes = List()
209 194 def _classes_default(self):
210 195 """This has to be in a method, for TerminalIPythonApp to be available."""
211 196 return [
212 197 InteractiveShellApp, # ShellApp comes before TerminalApp, because
213 198 self.__class__, # it will also affect subclasses (e.g. QtConsole)
214 199 TerminalInteractiveShell,
215 200 PromptManager,
216 201 HistoryManager,
217 202 ProfileDir,
218 203 PlainTextFormatter,
219 204 IPCompleter,
220 205 ScriptMagics,
221 206 StoreMagics,
222 207 ]
223 208
224 209 subcommands = dict(
225 210 qtconsole=('IPython.qt.console.qtconsoleapp.IPythonQtConsoleApp',
226 211 """Launch the IPython Qt Console."""
227 212 ),
228 213 notebook=('IPython.html.notebookapp.NotebookApp',
229 214 """Launch the IPython HTML Notebook Server."""
230 215 ),
231 216 profile = ("IPython.core.profileapp.ProfileApp",
232 217 "Create and manage IPython profiles."
233 218 ),
234 219 kernel = ("IPython.kernel.zmq.kernelapp.IPKernelApp",
235 220 "Start a kernel without an attached frontend."
236 221 ),
237 222 console=('IPython.terminal.console.app.ZMQTerminalIPythonApp',
238 223 """Launch the IPython terminal-based Console."""
239 224 ),
240 225 locate=('IPython.terminal.ipapp.LocateIPythonApp',
241 226 LocateIPythonApp.description
242 227 ),
243 228 history=('IPython.core.historyapp.HistoryApp',
244 229 "Manage the IPython history database."
245 230 ),
246 231 nbconvert=('IPython.nbconvert.nbconvertapp.NbConvertApp',
247 232 "Convert notebooks to/from other formats."
248 233 ),
249 234 trust=('IPython.nbformat.sign.TrustNotebookApp',
250 235 "Sign notebooks to trust their potentially unsafe contents at load."
251 236 ),
252 237 kernelspec=('IPython.kernel.kernelspecapp.KernelSpecApp',
253 238 "Manage IPython kernel specifications."
254 239 ),
255 240 )
256 241 subcommands['install-nbextension'] = (
257 242 "IPython.html.nbextensions.NBExtensionApp",
258 243 "Install IPython notebook extension files"
259 244 )
260 245
261 246 # *do* autocreate requested profile, but don't create the config file.
262 247 auto_create=Bool(True)
263 248 # configurables
264 249 ignore_old_config=Bool(False, config=True,
265 250 help="Suppress warning messages about legacy config files"
266 251 )
267 252 quick = Bool(False, config=True,
268 253 help="""Start IPython quickly by skipping the loading of config files."""
269 254 )
270 255 def _quick_changed(self, name, old, new):
271 256 if new:
272 257 self.load_config_file = lambda *a, **kw: None
273 258 self.ignore_old_config=True
274 259
275 260 display_banner = Bool(True, config=True,
276 261 help="Whether to display a banner upon starting IPython."
277 262 )
278 263
279 264 # if there is code of files to run from the cmd line, don't interact
280 265 # unless the --i flag (App.force_interact) is true.
281 266 force_interact = Bool(False, config=True,
282 267 help="""If a command or file is given via the command-line,
283 268 e.g. 'ipython foo.py', start an interactive shell after executing the
284 269 file or command."""
285 270 )
286 271 def _force_interact_changed(self, name, old, new):
287 272 if new:
288 273 self.interact = True
289 274
290 275 def _file_to_run_changed(self, name, old, new):
291 276 if new:
292 277 self.something_to_run = True
293 278 if new and not self.force_interact:
294 279 self.interact = False
295 280 _code_to_run_changed = _file_to_run_changed
296 281 _module_to_run_changed = _file_to_run_changed
297 282
298 283 # internal, not-configurable
299 284 interact=Bool(True)
300 285 something_to_run=Bool(False)
301 286
302 287 def parse_command_line(self, argv=None):
303 288 """override to allow old '-pylab' flag with deprecation warning"""
304 289
305 290 argv = sys.argv[1:] if argv is None else argv
306 291
307 292 if '-pylab' in argv:
308 293 # deprecated `-pylab` given,
309 294 # warn and transform into current syntax
310 295 argv = argv[:] # copy, don't clobber
311 296 idx = argv.index('-pylab')
312 297 warn.warn("`-pylab` flag has been deprecated.\n"
313 298 " Use `--matplotlib <backend>` and import pylab manually.")
314 299 argv[idx] = '--pylab'
315 300
316 301 return super(TerminalIPythonApp, self).parse_command_line(argv)
317 302
318 303 @catch_config_error
319 304 def initialize(self, argv=None):
320 305 """Do actions after construct, but before starting the app."""
321 306 super(TerminalIPythonApp, self).initialize(argv)
322 307 if self.subapp is not None:
323 308 # don't bother initializing further, starting subapp
324 309 return
325 310 if not self.ignore_old_config:
326 311 check_for_old_config(self.ipython_dir)
327 312 # print self.extra_args
328 313 if self.extra_args and not self.something_to_run:
329 314 self.file_to_run = self.extra_args[0]
330 315 self.init_path()
331 316 # create the shell
332 317 self.init_shell()
333 318 # and draw the banner
334 319 self.init_banner()
335 320 # Now a variety of things that happen after the banner is printed.
336 321 self.init_gui_pylab()
337 322 self.init_extensions()
338 323 self.init_code()
339 324
340 325 def init_shell(self):
341 326 """initialize the InteractiveShell instance"""
342 327 # Create an InteractiveShell instance.
343 328 # shell.display_banner should always be False for the terminal
344 329 # based app, because we call shell.show_banner() by hand below
345 330 # so the banner shows *before* all extension loading stuff.
346 331 self.shell = TerminalInteractiveShell.instance(parent=self,
347 332 display_banner=False, profile_dir=self.profile_dir,
348 333 ipython_dir=self.ipython_dir, user_ns=self.user_ns)
349 334 self.shell.configurables.append(self)
350 335
351 336 def init_banner(self):
352 337 """optionally display the banner"""
353 338 if self.display_banner and self.interact:
354 339 self.shell.show_banner()
355 340 # Make sure there is a space below the banner.
356 341 if self.log_level <= logging.INFO: print()
357 342
358 343 def _pylab_changed(self, name, old, new):
359 344 """Replace --pylab='inline' with --pylab='auto'"""
360 345 if new == 'inline':
361 346 warn.warn("'inline' not available as pylab backend, "
362 347 "using 'auto' instead.")
363 348 self.pylab = 'auto'
364 349
365 350 def start(self):
366 351 if self.subapp is not None:
367 352 return self.subapp.start()
368 353 # perform any prexec steps:
369 354 if self.interact:
370 355 self.log.debug("Starting IPython's mainloop...")
371 356 self.shell.mainloop()
372 357 else:
373 358 self.log.debug("IPython not interactive...")
374 359
375 360 def load_default_config(ipython_dir=None):
376 361 """Load the default config file from the default ipython_dir.
377 362
378 363 This is useful for embedded shells.
379 364 """
380 365 if ipython_dir is None:
381 366 ipython_dir = get_ipython_dir()
382 367
383 368 profile_dir = os.path.join(ipython_dir, 'profile_default')
384 369
385 370 config = Config()
386 371 for cf in Application._load_config_files("ipython_config", path=profile_dir):
387 372 config.update(cf)
388 373
389 374 return config
390 375
391 376 launch_new_instance = TerminalIPythonApp.launch_instance
392 377
393 378
394 379 if __name__ == '__main__':
395 380 launch_new_instance()
@@ -1,149 +1,145 b''
1 1 """ A minimal application using the ZMQ-based terminal IPython frontend.
2 2
3 3 This is not a complete console app, as subprocess will not be able to receive
4 4 input, there is no real readline support, among other limitations.
5
6 Authors:
7
8 * Min RK
9 * Paul Ivanov
10
11 5 """
12 6
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
7 # Copyright (c) IPython Development Team.
8 # Distributed under the terms of the Modified BSD License.
9
16 10 import signal
17 11
18 12 from IPython.terminal.ipapp import TerminalIPythonApp, frontend_flags as term_flags
19 13
20 14 from IPython.utils.traitlets import (
21 15 Dict, Any
22 16 )
23 17 from IPython.utils.warn import error
24 18
25 19 from IPython.consoleapp import (
26 20 IPythonConsoleApp, app_aliases, app_flags, aliases, flags
27 21 )
28 22
29 23 from IPython.terminal.console.interactiveshell import ZMQTerminalInteractiveShell
30 24
31 25 #-----------------------------------------------------------------------------
32 26 # Globals
33 27 #-----------------------------------------------------------------------------
34 28
35 29 _examples = """
36 30 ipython console # start the ZMQ-based console
37 31 ipython console --existing # connect to an existing ipython session
38 32 """
39 33
40 34 #-----------------------------------------------------------------------------
41 35 # Flags and Aliases
42 36 #-----------------------------------------------------------------------------
43 37
44 38 # copy flags from mixin:
45 39 flags = dict(flags)
46 40 # start with mixin frontend flags:
47 41 frontend_flags = dict(app_flags)
48 42 # add TerminalIPApp flags:
49 43 frontend_flags.update(term_flags)
50 44 # disable quick startup, as it won't propagate to the kernel anyway
51 45 frontend_flags.pop('quick')
52 46 # update full dict with frontend flags:
53 47 flags.update(frontend_flags)
54 48
55 49 # copy flags from mixin
56 50 aliases = dict(aliases)
57 51 # start with mixin frontend flags
58 52 frontend_aliases = dict(app_aliases)
59 53 # load updated frontend flags into full dict
60 54 aliases.update(frontend_aliases)
61 55
62 56 # get flags&aliases into sets, and remove a couple that
63 57 # shouldn't be scrubbed from backend flags:
64 58 frontend_aliases = set(frontend_aliases.keys())
65 59 frontend_flags = set(frontend_flags.keys())
66 60
67 61
68 62 #-----------------------------------------------------------------------------
69 63 # Classes
70 64 #-----------------------------------------------------------------------------
71 65
72 66
73 67 class ZMQTerminalIPythonApp(TerminalIPythonApp, IPythonConsoleApp):
74 68 name = "ipython-console"
75 69 """Start a terminal frontend to the IPython zmq kernel."""
76 70
77 71 description = """
78 72 The IPython terminal-based Console.
79 73
80 74 This launches a Console application inside a terminal.
81 75
82 76 The Console supports various extra features beyond the traditional
83 77 single-process Terminal IPython shell, such as connecting to an
84 78 existing ipython session, via:
85 79
86 80 ipython console --existing
87 81
88 82 where the previous session could have been created by another ipython
89 83 console, an ipython qtconsole, or by opening an ipython notebook.
90 84
91 85 """
92 86 examples = _examples
93 87
94 88 classes = [ZMQTerminalInteractiveShell] + IPythonConsoleApp.classes
95 89 flags = Dict(flags)
96 90 aliases = Dict(aliases)
97 91 frontend_aliases = Any(frontend_aliases)
98 92 frontend_flags = Any(frontend_flags)
99 93
100 94 subcommands = Dict()
95
96 force_interact = True
101 97
102 98 def parse_command_line(self, argv=None):
103 99 super(ZMQTerminalIPythonApp, self).parse_command_line(argv)
104 self.build_kernel_argv(argv)
100 self.build_kernel_argv(self.extra_args)
105 101
106 102 def init_shell(self):
107 103 IPythonConsoleApp.initialize(self)
108 104 # relay sigint to kernel
109 105 signal.signal(signal.SIGINT, self.handle_sigint)
110 106 self.shell = ZMQTerminalInteractiveShell.instance(parent=self,
111 107 display_banner=False, profile_dir=self.profile_dir,
112 108 ipython_dir=self.ipython_dir,
113 109 manager=self.kernel_manager,
114 110 client=self.kernel_client,
115 111 )
116 112
117 113 def init_gui_pylab(self):
118 114 # no-op, because we don't want to import matplotlib in the frontend.
119 115 pass
120 116
121 117 def handle_sigint(self, *args):
122 118 if self.shell._executing:
123 119 if self.kernel_manager:
124 120 # interrupt already gets passed to subprocess by signal handler.
125 121 # Only if we prevent that should we need to explicitly call
126 122 # interrupt_kernel, until which time, this would result in a
127 123 # double-interrupt:
128 124 # self.kernel_manager.interrupt_kernel()
129 125 pass
130 126 else:
131 127 self.shell.write_err('\n')
132 128 error("Cannot interrupt kernels we didn't start.\n")
133 129 else:
134 130 # raise the KeyboardInterrupt if we aren't waiting for execution,
135 131 # so that the interact loop advances, and prompt is redrawn, etc.
136 132 raise KeyboardInterrupt
137 133
138 134
139 135 def init_code(self):
140 136 # no-op in the frontend, code gets run in the backend
141 137 pass
142 138
143 139
144 140 launch_new_instance = ZMQTerminalIPythonApp.launch_instance
145 141
146 142
147 143 if __name__ == '__main__':
148 144 launch_new_instance()
149 145
@@ -1,386 +1,379 b''
1 1 """ A minimal application using the Qt console-style IPython frontend.
2 2
3 3 This is not a complete console app, as subprocess will not be able to receive
4 4 input, there is no real readline support, among other limitations.
5 5 """
6 6
7 7 # Copyright (c) IPython Development Team.
8 # Distributed under the terms of the Modified BSD License.
8 # Distributed under the terms of the Modified BSD License.
9 9
10 #-----------------------------------------------------------------------------
11 # Imports
12 #-----------------------------------------------------------------------------
13
14 # stdlib imports
15 10 import os
16 11 import signal
17 12 import sys
18 13
19 14 # If run on Windows, install an exception hook which pops up a
20 15 # message box. Pythonw.exe hides the console, so without this
21 16 # the application silently fails to load.
22 17 #
23 18 # We always install this handler, because the expectation is for
24 19 # qtconsole to bring up a GUI even if called from the console.
25 20 # The old handler is called, so the exception is printed as well.
26 21 # If desired, check for pythonw with an additional condition
27 22 # (sys.executable.lower().find('pythonw.exe') >= 0).
28 23 if os.name == 'nt':
29 24 old_excepthook = sys.excepthook
30 25
31 26 # Exclude this from our autogenerated API docs.
32 27 undoc = lambda func: func
33 28
34 29 @undoc
35 30 def gui_excepthook(exctype, value, tb):
36 31 try:
37 32 import ctypes, traceback
38 33 MB_ICONERROR = 0x00000010
39 34 title = u'Error starting IPython QtConsole'
40 35 msg = u''.join(traceback.format_exception(exctype, value, tb))
41 36 ctypes.windll.user32.MessageBoxW(0, msg, title, MB_ICONERROR)
42 37 finally:
43 38 # Also call the old exception hook to let it do
44 39 # its thing too.
45 40 old_excepthook(exctype, value, tb)
46 41
47 42 sys.excepthook = gui_excepthook
48 43
49 # System library imports
50 44 from IPython.external.qt import QtCore, QtGui
51 45
52 # Local imports
53 46 from IPython.config.application import boolean_flag
54 47 from IPython.config.application import catch_config_error
55 48 from IPython.core.application import BaseIPythonApplication
56 49 from IPython.qt.console.ipython_widget import IPythonWidget
57 50 from IPython.qt.console.rich_ipython_widget import RichIPythonWidget
58 51 from IPython.qt.console import styles
59 52 from IPython.qt.console.mainwindow import MainWindow
60 53 from IPython.qt.client import QtKernelClient
61 54 from IPython.qt.manager import QtKernelManager
62 55 from IPython.utils.traitlets import (
63 56 Dict, Unicode, CBool, Any
64 57 )
65 58
66 59 from IPython.consoleapp import (
67 60 IPythonConsoleApp, app_aliases, app_flags, flags, aliases
68 61 )
69 62
70 63 #-----------------------------------------------------------------------------
71 64 # Network Constants
72 65 #-----------------------------------------------------------------------------
73 66
74 67 from IPython.utils.localinterfaces import is_local_ip
75 68
76 69 #-----------------------------------------------------------------------------
77 70 # Globals
78 71 #-----------------------------------------------------------------------------
79 72
80 73 _examples = """
81 74 ipython qtconsole # start the qtconsole
82 75 ipython qtconsole --matplotlib=inline # start with matplotlib inline plotting mode
83 76 """
84 77
85 78 #-----------------------------------------------------------------------------
86 79 # Aliases and Flags
87 80 #-----------------------------------------------------------------------------
88 81
89 82 # start with copy of flags
90 83 flags = dict(flags)
91 84 qt_flags = {
92 85 'plain' : ({'IPythonQtConsoleApp' : {'plain' : True}},
93 86 "Disable rich text support."),
94 87 }
95 88 qt_flags.update(boolean_flag(
96 89 'banner', 'IPythonQtConsoleApp.display_banner',
97 90 "Display a banner upon starting the QtConsole.",
98 91 "Don't display a banner upon starting the QtConsole."
99 92 ))
100 93
101 94 # and app_flags from the Console Mixin
102 95 qt_flags.update(app_flags)
103 96 # add frontend flags to the full set
104 97 flags.update(qt_flags)
105 98
106 99 # start with copy of front&backend aliases list
107 100 aliases = dict(aliases)
108 101 qt_aliases = dict(
109 102 style = 'IPythonWidget.syntax_style',
110 103 stylesheet = 'IPythonQtConsoleApp.stylesheet',
111 104 colors = 'ZMQInteractiveShell.colors',
112 105
113 106 editor = 'IPythonWidget.editor',
114 107 paging = 'ConsoleWidget.paging',
115 108 )
116 109 # and app_aliases from the Console Mixin
117 110 qt_aliases.update(app_aliases)
118 111 qt_aliases.update({'gui-completion':'ConsoleWidget.gui_completion'})
119 112 # add frontend aliases to the full set
120 113 aliases.update(qt_aliases)
121 114
122 115 # get flags&aliases into sets, and remove a couple that
123 116 # shouldn't be scrubbed from backend flags:
124 117 qt_aliases = set(qt_aliases.keys())
125 118 qt_aliases.remove('colors')
126 119 qt_flags = set(qt_flags.keys())
127 120
128 121 #-----------------------------------------------------------------------------
129 122 # Classes
130 123 #-----------------------------------------------------------------------------
131 124
132 125 #-----------------------------------------------------------------------------
133 126 # IPythonQtConsole
134 127 #-----------------------------------------------------------------------------
135 128
136 129
137 130 class IPythonQtConsoleApp(BaseIPythonApplication, IPythonConsoleApp):
138 131 name = 'ipython-qtconsole'
139 132
140 133 description = """
141 134 The IPython QtConsole.
142 135
143 136 This launches a Console-style application using Qt. It is not a full
144 137 console, in that launched terminal subprocesses will not be able to accept
145 138 input.
146 139
147 140 The QtConsole supports various extra features beyond the Terminal IPython
148 141 shell, such as inline plotting with matplotlib, via:
149 142
150 143 ipython qtconsole --matplotlib=inline
151 144
152 145 as well as saving your session as HTML, and printing the output.
153 146
154 147 """
155 148 examples = _examples
156 149
157 150 classes = [IPythonWidget] + IPythonConsoleApp.classes
158 151 flags = Dict(flags)
159 152 aliases = Dict(aliases)
160 153 frontend_flags = Any(qt_flags)
161 154 frontend_aliases = Any(qt_aliases)
162 155 kernel_client_class = QtKernelClient
163 156 kernel_manager_class = QtKernelManager
164 157
165 158 stylesheet = Unicode('', config=True,
166 159 help="path to a custom CSS stylesheet")
167 160
168 161 hide_menubar = CBool(False, config=True,
169 162 help="Start the console window with the menu bar hidden.")
170 163
171 164 maximize = CBool(False, config=True,
172 165 help="Start the console window maximized.")
173 166
174 167 plain = CBool(False, config=True,
175 168 help="Use a plaintext widget instead of rich text (plain can't print/save).")
176 169
177 170 display_banner = CBool(True, config=True,
178 171 help="Whether to display a banner upon starting the QtConsole."
179 172 )
180 173
181 174 def _plain_changed(self, name, old, new):
182 175 kind = 'plain' if new else 'rich'
183 176 self.config.ConsoleWidget.kind = kind
184 177 if new:
185 178 self.widget_factory = IPythonWidget
186 179 else:
187 180 self.widget_factory = RichIPythonWidget
188 181
189 182 # the factory for creating a widget
190 183 widget_factory = Any(RichIPythonWidget)
191 184
192 185 def parse_command_line(self, argv=None):
193 186 super(IPythonQtConsoleApp, self).parse_command_line(argv)
194 self.build_kernel_argv(argv)
187 self.build_kernel_argv(self.extra_args)
195 188
196 189
197 190 def new_frontend_master(self):
198 191 """ Create and return new frontend attached to new kernel, launched on localhost.
199 192 """
200 193 kernel_manager = self.kernel_manager_class(
201 194 connection_file=self._new_connection_file(),
202 195 parent=self,
203 196 autorestart=True,
204 197 )
205 198 # start the kernel
206 199 kwargs = {}
207 200 # FIXME: remove special treatment of IPython kernels
208 201 if self.kernel_manager.ipython_kernel:
209 202 kwargs['extra_arguments'] = self.kernel_argv
210 203 kernel_manager.start_kernel(**kwargs)
211 204 kernel_manager.client_factory = self.kernel_client_class
212 205 kernel_client = kernel_manager.client()
213 206 kernel_client.start_channels(shell=True, iopub=True)
214 207 widget = self.widget_factory(config=self.config,
215 208 local_kernel=True)
216 209 self.init_colors(widget)
217 210 widget.kernel_manager = kernel_manager
218 211 widget.kernel_client = kernel_client
219 212 widget._existing = False
220 213 widget._may_close = True
221 214 widget._confirm_exit = self.confirm_exit
222 215 widget._display_banner = self.display_banner
223 216 return widget
224 217
225 218 def new_frontend_slave(self, current_widget):
226 219 """Create and return a new frontend attached to an existing kernel.
227 220
228 221 Parameters
229 222 ----------
230 223 current_widget : IPythonWidget
231 224 The IPythonWidget whose kernel this frontend is to share
232 225 """
233 226 kernel_client = self.kernel_client_class(
234 227 connection_file=current_widget.kernel_client.connection_file,
235 228 config = self.config,
236 229 )
237 230 kernel_client.load_connection_file()
238 231 kernel_client.start_channels()
239 232 widget = self.widget_factory(config=self.config,
240 233 local_kernel=False)
241 234 self.init_colors(widget)
242 235 widget._existing = True
243 236 widget._may_close = False
244 237 widget._confirm_exit = False
245 238 widget._display_banner = self.display_banner
246 239 widget.kernel_client = kernel_client
247 240 widget.kernel_manager = current_widget.kernel_manager
248 241 return widget
249 242
250 243 def init_qt_app(self):
251 244 # separate from qt_elements, because it must run first
252 245 self.app = QtGui.QApplication([])
253 246
254 247 def init_qt_elements(self):
255 248 # Create the widget.
256 249
257 250 base_path = os.path.abspath(os.path.dirname(__file__))
258 251 icon_path = os.path.join(base_path, 'resources', 'icon', 'IPythonConsole.svg')
259 252 self.app.icon = QtGui.QIcon(icon_path)
260 253 QtGui.QApplication.setWindowIcon(self.app.icon)
261 254
262 255 ip = self.ip
263 256 local_kernel = (not self.existing) or is_local_ip(ip)
264 257 self.widget = self.widget_factory(config=self.config,
265 258 local_kernel=local_kernel)
266 259 self.init_colors(self.widget)
267 260 self.widget._existing = self.existing
268 261 self.widget._may_close = not self.existing
269 262 self.widget._confirm_exit = self.confirm_exit
270 263 self.widget._display_banner = self.display_banner
271 264
272 265 self.widget.kernel_manager = self.kernel_manager
273 266 self.widget.kernel_client = self.kernel_client
274 267 self.window = MainWindow(self.app,
275 268 confirm_exit=self.confirm_exit,
276 269 new_frontend_factory=self.new_frontend_master,
277 270 slave_frontend_factory=self.new_frontend_slave,
278 271 )
279 272 self.window.log = self.log
280 273 self.window.add_tab_with_frontend(self.widget)
281 274 self.window.init_magic_helper()
282 275 self.window.init_menu_bar()
283 276
284 277 # Ignore on OSX, where there is always a menu bar
285 278 if sys.platform != 'darwin' and self.hide_menubar:
286 279 self.window.menuBar().setVisible(False)
287 280
288 281 self.window.setWindowTitle('IPython')
289 282
290 283 def init_colors(self, widget):
291 284 """Configure the coloring of the widget"""
292 285 # Note: This will be dramatically simplified when colors
293 286 # are removed from the backend.
294 287
295 288 # parse the colors arg down to current known labels
296 289 cfg = self.config
297 290 colors = cfg.ZMQInteractiveShell.colors if 'ZMQInteractiveShell.colors' in cfg else None
298 291 style = cfg.IPythonWidget.syntax_style if 'IPythonWidget.syntax_style' in cfg else None
299 292 sheet = cfg.IPythonWidget.style_sheet if 'IPythonWidget.style_sheet' in cfg else None
300 293
301 294 # find the value for colors:
302 295 if colors:
303 296 colors=colors.lower()
304 297 if colors in ('lightbg', 'light'):
305 298 colors='lightbg'
306 299 elif colors in ('dark', 'linux'):
307 300 colors='linux'
308 301 else:
309 302 colors='nocolor'
310 303 elif style:
311 304 if style=='bw':
312 305 colors='nocolor'
313 306 elif styles.dark_style(style):
314 307 colors='linux'
315 308 else:
316 309 colors='lightbg'
317 310 else:
318 311 colors=None
319 312
320 313 # Configure the style
321 314 if style:
322 315 widget.style_sheet = styles.sheet_from_template(style, colors)
323 316 widget.syntax_style = style
324 317 widget._syntax_style_changed()
325 318 widget._style_sheet_changed()
326 319 elif colors:
327 320 # use a default dark/light/bw style
328 321 widget.set_default_style(colors=colors)
329 322
330 323 if self.stylesheet:
331 324 # we got an explicit stylesheet
332 325 if os.path.isfile(self.stylesheet):
333 326 with open(self.stylesheet) as f:
334 327 sheet = f.read()
335 328 else:
336 329 raise IOError("Stylesheet %r not found." % self.stylesheet)
337 330 if sheet:
338 331 widget.style_sheet = sheet
339 332 widget._style_sheet_changed()
340 333
341 334
342 335 def init_signal(self):
343 336 """allow clean shutdown on sigint"""
344 337 signal.signal(signal.SIGINT, lambda sig, frame: self.exit(-2))
345 338 # need a timer, so that QApplication doesn't block until a real
346 339 # Qt event fires (can require mouse movement)
347 340 # timer trick from http://stackoverflow.com/q/4938723/938949
348 341 timer = QtCore.QTimer()
349 342 # Let the interpreter run each 200 ms:
350 343 timer.timeout.connect(lambda: None)
351 344 timer.start(200)
352 345 # hold onto ref, so the timer doesn't get cleaned up
353 346 self._sigint_timer = timer
354 347
355 348 @catch_config_error
356 349 def initialize(self, argv=None):
357 350 self.init_qt_app()
358 351 super(IPythonQtConsoleApp, self).initialize(argv)
359 352 IPythonConsoleApp.initialize(self,argv)
360 353 self.init_qt_elements()
361 354 self.init_signal()
362 355
363 356 def start(self):
364 357
365 358 # draw the window
366 359 if self.maximize:
367 360 self.window.showMaximized()
368 361 else:
369 362 self.window.show()
370 363 self.window.raise_()
371 364
372 365 # Start the application main loop.
373 366 self.app.exec_()
374 367
375 368 #-----------------------------------------------------------------------------
376 369 # Main entry point
377 370 #-----------------------------------------------------------------------------
378 371
379 372 def main():
380 373 app = IPythonQtConsoleApp()
381 374 app.initialize()
382 375 app.start()
383 376
384 377
385 378 if __name__ == '__main__':
386 379 main()
General Comments 0
You need to be logged in to leave comments. Login now