##// END OF EJS Templates
add qtconsole as subapp of terminal ipapp...
MinRK -
Show More
@@ -1,354 +1,365 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 """
4 4 The :class:`~IPython.core.newapplication.Application` object for the command
5 5 line :command:`ipython` program.
6 6
7 7 Authors
8 8 -------
9 9
10 10 * Brian Granger
11 11 * Fernando Perez
12 12 * Min Ragan-Kelley
13 13 """
14 14
15 15 #-----------------------------------------------------------------------------
16 16 # Copyright (C) 2008-2010 The IPython Development Team
17 17 #
18 18 # Distributed under the terms of the BSD License. The full license is in
19 19 # the file COPYING, distributed as part of this software.
20 20 #-----------------------------------------------------------------------------
21 21
22 22 #-----------------------------------------------------------------------------
23 23 # Imports
24 24 #-----------------------------------------------------------------------------
25 25
26 26 from __future__ import absolute_import
27 27
28 28 import logging
29 29 import os
30 30 import sys
31 31
32 32 from IPython.config.loader import (
33 33 Config, PyFileConfigLoader
34 34 )
35 35 from IPython.config.application import boolean_flag
36 36 from IPython.core import release
37 37 from IPython.core import usage
38 38 from IPython.core.crashhandler import CrashHandler
39 39 from IPython.core.formatters import PlainTextFormatter
40 40 from IPython.core.newapplication import (
41 41 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
42 42 )
43 43 from IPython.core.shellapp import (
44 44 InteractiveShellApp, shell_flags, shell_aliases
45 45 )
46 46 from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
47 47 from IPython.lib import inputhook
48 48 from IPython.utils.path import get_ipython_dir, check_for_old_config
49 49 from IPython.utils.traitlets import (
50 50 Bool, Dict, CaselessStrEnum
51 51 )
52 52
53 53 #-----------------------------------------------------------------------------
54 54 # Globals, utilities and helpers
55 55 #-----------------------------------------------------------------------------
56 56
57 57 #: The default config file name for this application.
58 58 default_config_file_name = u'ipython_config.py'
59 59
60 60
61 61 #-----------------------------------------------------------------------------
62 62 # Crash handler for this application
63 63 #-----------------------------------------------------------------------------
64 64
65 65 _message_template = """\
66 66 Oops, $self.app_name crashed. We do our best to make it stable, but...
67 67
68 68 A crash report was automatically generated with the following information:
69 69 - A verbatim copy of the crash traceback.
70 70 - A copy of your input history during this session.
71 71 - Data on your current $self.app_name configuration.
72 72
73 73 It was left in the file named:
74 74 \t'$self.crash_report_fname'
75 75 If you can email this file to the developers, the information in it will help
76 76 them in understanding and correcting the problem.
77 77
78 78 You can mail it to: $self.contact_name at $self.contact_email
79 79 with the subject '$self.app_name Crash Report'.
80 80
81 81 If you want to do it now, the following command will work (under Unix):
82 82 mail -s '$self.app_name Crash Report' $self.contact_email < $self.crash_report_fname
83 83
84 84 To ensure accurate tracking of this issue, please file a report about it at:
85 85 $self.bug_tracker
86 86 """
87 87
88 88 class IPAppCrashHandler(CrashHandler):
89 89 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
90 90
91 91 message_template = _message_template
92 92
93 93 def __init__(self, app):
94 94 contact_name = release.authors['Fernando'][0]
95 95 contact_email = release.authors['Fernando'][1]
96 96 bug_tracker = 'http://github.com/ipython/ipython/issues'
97 97 super(IPAppCrashHandler,self).__init__(
98 98 app, contact_name, contact_email, bug_tracker
99 99 )
100 100
101 101 def make_report(self,traceback):
102 102 """Return a string containing a crash report."""
103 103
104 104 sec_sep = self.section_sep
105 105 # Start with parent report
106 106 report = [super(IPAppCrashHandler, self).make_report(traceback)]
107 107 # Add interactive-specific info we may have
108 108 rpt_add = report.append
109 109 try:
110 110 rpt_add(sec_sep+"History of session input:")
111 111 for line in self.app.shell.user_ns['_ih']:
112 112 rpt_add(line)
113 113 rpt_add('\n*** Last line of input (may not be in above history):\n')
114 114 rpt_add(self.app.shell._last_input_line+'\n')
115 115 except:
116 116 pass
117 117
118 118 return ''.join(report)
119 119
120 120 #-----------------------------------------------------------------------------
121 121 # Aliases and Flags
122 122 #-----------------------------------------------------------------------------
123 123 flags = dict(base_flags)
124 124 flags.update(shell_flags)
125 125 addflag = lambda *args: flags.update(boolean_flag(*args))
126 126 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
127 127 'Turn on auto editing of files with syntax errors.',
128 128 'Turn off auto editing of files with syntax errors.'
129 129 )
130 130 addflag('banner', 'TerminalIPythonApp.display_banner',
131 131 "Display a banner upon starting IPython.",
132 132 "Don't display a banner upon starting IPython."
133 133 )
134 134 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
135 135 """Set to confirm when you try to exit IPython with an EOF (Control-D
136 136 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
137 137 you can force a direct exit without any confirmation.""",
138 138 "Don't prompt the user when exiting."
139 139 )
140 140 addflag('term-title', 'TerminalInteractiveShell.term_title',
141 141 "Enable auto setting the terminal title.",
142 142 "Disable auto setting the terminal title."
143 143 )
144 144 classic_config = Config()
145 145 classic_config.InteractiveShell.cache_size = 0
146 146 classic_config.PlainTextFormatter.pprint = False
147 147 classic_config.InteractiveShell.prompt_in1 = '>>> '
148 148 classic_config.InteractiveShell.prompt_in2 = '... '
149 149 classic_config.InteractiveShell.prompt_out = ''
150 150 classic_config.InteractiveShell.separate_in = ''
151 151 classic_config.InteractiveShell.separate_out = ''
152 152 classic_config.InteractiveShell.separate_out2 = ''
153 153 classic_config.InteractiveShell.colors = 'NoColor'
154 154 classic_config.InteractiveShell.xmode = 'Plain'
155 155
156 156 flags['classic']=(
157 157 classic_config,
158 158 "Gives IPython a similar feel to the classic Python prompt."
159 159 )
160 160 # # log doesn't make so much sense this way anymore
161 161 # paa('--log','-l',
162 162 # action='store_true', dest='InteractiveShell.logstart',
163 163 # help="Start logging to the default log file (./ipython_log.py).")
164 164 #
165 165 # # quick is harder to implement
166 166 flags['quick']=(
167 167 {'TerminalIPythonApp' : {'quick' : True}},
168 168 "Enable quick startup with no config files."
169 169 )
170 170
171 171 nosep_config = Config()
172 172 nosep_config.InteractiveShell.separate_in = ''
173 173 nosep_config.InteractiveShell.separate_out = ''
174 174 nosep_config.InteractiveShell.separate_out2 = ''
175 175
176 176 flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
177 177
178 178 flags['i'] = (
179 179 {'TerminalIPythonApp' : {'force_interact' : True}},
180 180 "If running code from the command line, become interactive afterwards."
181 181 )
182 182 flags['pylab'] = (
183 183 {'TerminalIPythonApp' : {'pylab' : 'auto'}},
184 184 """Pre-load matplotlib and numpy for interactive use with
185 185 the default matplotlib backend."""
186 186 )
187 187
188 188 aliases = dict(base_aliases)
189 189 aliases.update(shell_aliases)
190 190
191 191 # it's possible we don't want short aliases for *all* of these:
192 192 aliases.update(dict(
193 193 editor='TerminalInteractiveShell.editor',
194 194 sl='TerminalInteractiveShell.screen_length',
195 195 gui='TerminalIPythonApp.gui',
196 196 pylab='TerminalIPythonApp.pylab',
197 197 ))
198 198
199 199 #-----------------------------------------------------------------------------
200 200 # Main classes and functions
201 201 #-----------------------------------------------------------------------------
202 202
203 203 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
204 204 name = u'ipython'
205 205 description = usage.cl_usage
206 206 # command_line_loader = IPAppConfigLoader
207 207 default_config_file_name = default_config_file_name
208 208 crash_handler_class = IPAppCrashHandler
209
209 210 flags = Dict(flags)
210 211 aliases = Dict(aliases)
211 212 classes = [InteractiveShellApp, TerminalInteractiveShell, ProfileDir, PlainTextFormatter]
213 subcommands = Dict(dict(
214 qtconsole=('IPython.frontend.qt.console.ipythonqt.IPythonQtConsoleApp',
215 """Launch the IPython QtConsole. Also launched as ipython-qtconsole"""
216 )
217 ))
218
212 219 # *do* autocreate requested profile
213 220 auto_create=Bool(True)
214 221 copy_config_files=Bool(True)
215 222 # configurables
216 223 ignore_old_config=Bool(False, config=True,
217 224 help="Suppress warning messages about legacy config files"
218 225 )
219 226 quick = Bool(False, config=True,
220 227 help="""Start IPython quickly by skipping the loading of config files."""
221 228 )
222 229 def _quick_changed(self, name, old, new):
223 230 if new:
224 231 self.load_config_file = lambda *a, **kw: None
225 232 self.ignore_old_config=True
226 233
227 234 gui = CaselessStrEnum(('qt','wx','gtk'), config=True,
228 235 help="Enable GUI event loop integration ('qt', 'wx', 'gtk')."
229 236 )
230 237 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'auto'],
231 238 config=True,
232 239 help="""Pre-load matplotlib and numpy for interactive use,
233 240 selecting a particular matplotlib backend and loop integration.
234 241 """
235 242 )
236 243 display_banner = Bool(True, config=True,
237 244 help="Whether to display a banner upon starting IPython."
238 245 )
239 246
240 247 # if there is code of files to run from the cmd line, don't interact
241 248 # unless the --i flag (App.force_interact) is true.
242 249 force_interact = Bool(False, config=True,
243 250 help="""If a command or file is given via the command-line,
244 251 e.g. 'ipython foo.py"""
245 252 )
246 253 def _force_interact_changed(self, name, old, new):
247 254 if new:
248 255 self.interact = True
249 256
250 257 def _file_to_run_changed(self, name, old, new):
251 258 if new and not self.force_interact:
252 259 self.interact = False
253 260 _code_to_run_changed = _file_to_run_changed
254 261
255 262 # internal, not-configurable
256 263 interact=Bool(True)
257 264
258 265
259 266 def initialize(self, argv=None):
260 267 """Do actions after construct, but before starting the app."""
261 268 super(TerminalIPythonApp, self).initialize(argv)
269 if self.subapp is not None:
270 # don't bother initializing further, starting subapp
271 return
262 272 if not self.ignore_old_config:
263 273 check_for_old_config(self.ipython_dir)
264
265 274 # print self.extra_args
266 275 if self.extra_args:
267 276 self.file_to_run = self.extra_args[0]
268 277 # create the shell
269 278 self.init_shell()
270 279 # and draw the banner
271 280 self.init_banner()
272 281 # Now a variety of things that happen after the banner is printed.
273 282 self.init_gui_pylab()
274 283 self.init_extensions()
275 284 self.init_code()
276 285
277 286 def init_shell(self):
278 287 """initialize the InteractiveShell instance"""
279 288 # I am a little hesitant to put these into InteractiveShell itself.
280 289 # But that might be the place for them
281 290 sys.path.insert(0, '')
282 291
283 292 # Create an InteractiveShell instance.
284 293 # shell.display_banner should always be False for the terminal
285 294 # based app, because we call shell.show_banner() by hand below
286 295 # so the banner shows *before* all extension loading stuff.
287 296 self.shell = TerminalInteractiveShell.instance(config=self.config,
288 297 display_banner=False, profile_dir=self.profile_dir,
289 298 ipython_dir=self.ipython_dir)
290 299
291 300 def init_banner(self):
292 301 """optionally display the banner"""
293 302 if self.display_banner and self.interact:
294 303 self.shell.show_banner()
295 304 # Make sure there is a space below the banner.
296 305 if self.log_level <= logging.INFO: print
297 306
298 307
299 308 def init_gui_pylab(self):
300 309 """Enable GUI event loop integration, taking pylab into account."""
301 310 gui = self.gui
302 311
303 312 # Using `pylab` will also require gui activation, though which toolkit
304 313 # to use may be chosen automatically based on mpl configuration.
305 314 if self.pylab:
306 315 activate = self.shell.enable_pylab
307 316 if self.pylab == 'auto':
308 317 gui = None
309 318 else:
310 319 gui = self.pylab
311 320 else:
312 321 # Enable only GUI integration, no pylab
313 322 activate = inputhook.enable_gui
314 323
315 324 if gui or self.pylab:
316 325 try:
317 326 self.log.info("Enabling GUI event loop integration, "
318 327 "toolkit=%s, pylab=%s" % (gui, self.pylab) )
319 328 activate(gui)
320 329 except:
321 330 self.log.warn("Error in enabling GUI event loop integration:")
322 331 self.shell.showtraceback()
323 332
324 333 def start(self):
334 if self.subapp is not None:
335 return self.subapp.start()
325 336 # perform any prexec steps:
326 337 if self.interact:
327 338 self.log.debug("Starting IPython's mainloop...")
328 339 self.shell.mainloop()
329 340 else:
330 341 self.log.debug("IPython not interactive...")
331 342
332 343
333 344 def load_default_config(ipython_dir=None):
334 345 """Load the default config file from the default ipython_dir.
335 346
336 347 This is useful for embedded shells.
337 348 """
338 349 if ipython_dir is None:
339 350 ipython_dir = get_ipython_dir()
340 351 profile_dir = os.path.join(ipython_dir, 'profile_default')
341 352 cl = PyFileConfigLoader(default_config_file_name, profile_dir)
342 353 config = cl.load_config()
343 354 return config
344 355
345 356
346 357 def launch_new_instance():
347 358 """Create and run a full blown IPython instance"""
348 359 app = TerminalIPythonApp.instance()
349 360 app.initialize()
350 361 app.start()
351 362
352 363
353 364 if __name__ == '__main__':
354 365 launch_new_instance()
General Comments 0
You need to be logged in to leave comments. Login now