##// END OF EJS Templates
Add "something_to_run" flag which is set to True if there is a module, file, or code to run.
Bradley M. Froehle -
Show More
@@ -1,408 +1,410 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 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-2011 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, ConfigFileNotFound
34 34 )
35 35 from IPython.config.application import boolean_flag, catch_config_error
36 36 from IPython.core import release
37 37 from IPython.core import usage
38 38 from IPython.core.completer import IPCompleter
39 39 from IPython.core.crashhandler import CrashHandler
40 40 from IPython.core.formatters import PlainTextFormatter
41 41 from IPython.core.prompts import PromptManager
42 42 from IPython.core.application import (
43 43 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
44 44 )
45 45 from IPython.core.shellapp import (
46 46 InteractiveShellApp, shell_flags, shell_aliases
47 47 )
48 48 from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
49 49 from IPython.lib import inputhook
50 50 from IPython.utils import warn
51 51 from IPython.utils.path import get_ipython_dir, check_for_old_config
52 52 from IPython.utils.traitlets import (
53 53 Bool, List, Dict, CaselessStrEnum
54 54 )
55 55
56 56 #-----------------------------------------------------------------------------
57 57 # Globals, utilities and helpers
58 58 #-----------------------------------------------------------------------------
59 59
60 60 #: The default config file name for this application.
61 61 default_config_file_name = u'ipython_config.py'
62 62
63 63 _examples = """
64 64 ipython --pylab # start in pylab mode
65 65 ipython --pylab=qt # start in pylab mode with the qt4 backend
66 66 ipython --log-level=DEBUG # set logging to DEBUG
67 67 ipython --profile=foo # start with profile foo
68 68
69 69 ipython qtconsole # start the qtconsole GUI application
70 70 ipython qtconsole -h # show the help string for the qtconsole subcmd
71 71
72 72 ipython console # start the terminal-based console application
73 73 ipython console -h # show the help string for the console subcmd
74 74
75 75 ipython profile create foo # create profile foo w/ default config files
76 76 ipython profile -h # show the help string for the profile subcmd
77 77 """
78 78
79 79 #-----------------------------------------------------------------------------
80 80 # Crash handler for this application
81 81 #-----------------------------------------------------------------------------
82 82
83 83 class IPAppCrashHandler(CrashHandler):
84 84 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
85 85
86 86 def __init__(self, app):
87 87 contact_name = release.authors['Fernando'][0]
88 88 contact_email = release.author_email
89 89 bug_tracker = 'https://github.com/ipython/ipython/issues'
90 90 super(IPAppCrashHandler,self).__init__(
91 91 app, contact_name, contact_email, bug_tracker
92 92 )
93 93
94 94 def make_report(self,traceback):
95 95 """Return a string containing a crash report."""
96 96
97 97 sec_sep = self.section_sep
98 98 # Start with parent report
99 99 report = [super(IPAppCrashHandler, self).make_report(traceback)]
100 100 # Add interactive-specific info we may have
101 101 rpt_add = report.append
102 102 try:
103 103 rpt_add(sec_sep+"History of session input:")
104 104 for line in self.app.shell.user_ns['_ih']:
105 105 rpt_add(line)
106 106 rpt_add('\n*** Last line of input (may not be in above history):\n')
107 107 rpt_add(self.app.shell._last_input_line+'\n')
108 108 except:
109 109 pass
110 110
111 111 return ''.join(report)
112 112
113 113 #-----------------------------------------------------------------------------
114 114 # Aliases and Flags
115 115 #-----------------------------------------------------------------------------
116 116 flags = dict(base_flags)
117 117 flags.update(shell_flags)
118 118 frontend_flags = {}
119 119 addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
120 120 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
121 121 'Turn on auto editing of files with syntax errors.',
122 122 'Turn off auto editing of files with syntax errors.'
123 123 )
124 124 addflag('banner', 'TerminalIPythonApp.display_banner',
125 125 "Display a banner upon starting IPython.",
126 126 "Don't display a banner upon starting IPython."
127 127 )
128 128 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
129 129 """Set to confirm when you try to exit IPython with an EOF (Control-D
130 130 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
131 131 you can force a direct exit without any confirmation.""",
132 132 "Don't prompt the user when exiting."
133 133 )
134 134 addflag('term-title', 'TerminalInteractiveShell.term_title',
135 135 "Enable auto setting the terminal title.",
136 136 "Disable auto setting the terminal title."
137 137 )
138 138 classic_config = Config()
139 139 classic_config.InteractiveShell.cache_size = 0
140 140 classic_config.PlainTextFormatter.pprint = False
141 141 classic_config.PromptManager.in_template = '>>> '
142 142 classic_config.PromptManager.in2_template = '... '
143 143 classic_config.PromptManager.out_template = ''
144 144 classic_config.InteractiveShell.separate_in = ''
145 145 classic_config.InteractiveShell.separate_out = ''
146 146 classic_config.InteractiveShell.separate_out2 = ''
147 147 classic_config.InteractiveShell.colors = 'NoColor'
148 148 classic_config.InteractiveShell.xmode = 'Plain'
149 149
150 150 frontend_flags['classic']=(
151 151 classic_config,
152 152 "Gives IPython a similar feel to the classic Python prompt."
153 153 )
154 154 # # log doesn't make so much sense this way anymore
155 155 # paa('--log','-l',
156 156 # action='store_true', dest='InteractiveShell.logstart',
157 157 # help="Start logging to the default log file (./ipython_log.py).")
158 158 #
159 159 # # quick is harder to implement
160 160 frontend_flags['quick']=(
161 161 {'TerminalIPythonApp' : {'quick' : True}},
162 162 "Enable quick startup with no config files."
163 163 )
164 164
165 165 frontend_flags['i'] = (
166 166 {'TerminalIPythonApp' : {'force_interact' : True}},
167 167 """If running code from the command line, become interactive afterwards.
168 168 Note: can also be given simply as '-i.'"""
169 169 )
170 170 frontend_flags['pylab'] = (
171 171 {'TerminalIPythonApp' : {'pylab' : 'auto'}},
172 172 """Pre-load matplotlib and numpy for interactive use with
173 173 the default matplotlib backend."""
174 174 )
175 175 flags.update(frontend_flags)
176 176
177 177 aliases = dict(base_aliases)
178 178 aliases.update(shell_aliases)
179 179
180 180 # it's possible we don't want short aliases for *all* of these:
181 181 aliases.update(dict(
182 182 gui='TerminalIPythonApp.gui',
183 183 pylab='TerminalIPythonApp.pylab',
184 184 ))
185 185
186 186 #-----------------------------------------------------------------------------
187 187 # Main classes and functions
188 188 #-----------------------------------------------------------------------------
189 189
190 190 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
191 191 name = u'ipython'
192 192 description = usage.cl_usage
193 193 default_config_file_name = default_config_file_name
194 194 crash_handler_class = IPAppCrashHandler
195 195 examples = _examples
196 196
197 197 flags = Dict(flags)
198 198 aliases = Dict(aliases)
199 199 classes = List()
200 200 def _classes_default(self):
201 201 """This has to be in a method, for TerminalIPythonApp to be available."""
202 202 return [
203 203 InteractiveShellApp, # ShellApp comes before TerminalApp, because
204 204 self.__class__, # it will also affect subclasses (e.g. QtConsole)
205 205 TerminalInteractiveShell,
206 206 PromptManager,
207 207 ProfileDir,
208 208 PlainTextFormatter,
209 209 IPCompleter,
210 210 ]
211 211
212 212 subcommands = Dict(dict(
213 213 qtconsole=('IPython.frontend.qt.console.qtconsoleapp.IPythonQtConsoleApp',
214 214 """Launch the IPython Qt Console."""
215 215 ),
216 216 notebook=('IPython.frontend.html.notebook.notebookapp.NotebookApp',
217 217 """Launch the IPython HTML Notebook Server."""
218 218 ),
219 219 profile = ("IPython.core.profileapp.ProfileApp",
220 220 "Create and manage IPython profiles."
221 221 ),
222 222 kernel = ("IPython.zmq.ipkernel.IPKernelApp",
223 223 "Start a kernel without an attached frontend."
224 224 ),
225 225 console=('IPython.frontend.terminal.console.app.ZMQTerminalIPythonApp',
226 226 """Launch the IPython terminal-based Console."""
227 227 ),
228 228 ))
229 229
230 230 # *do* autocreate requested profile, but don't create the config file.
231 231 auto_create=Bool(True)
232 232 # configurables
233 233 ignore_old_config=Bool(False, config=True,
234 234 help="Suppress warning messages about legacy config files"
235 235 )
236 236 quick = Bool(False, config=True,
237 237 help="""Start IPython quickly by skipping the loading of config files."""
238 238 )
239 239 def _quick_changed(self, name, old, new):
240 240 if new:
241 241 self.load_config_file = lambda *a, **kw: None
242 242 self.ignore_old_config=True
243 243
244 244 gui = CaselessStrEnum(('qt', 'wx', 'gtk', 'glut', 'pyglet'), config=True,
245 245 help="Enable GUI event loop integration ('qt', 'wx', 'gtk', 'glut', 'pyglet')."
246 246 )
247 247 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'auto'],
248 248 config=True,
249 249 help="""Pre-load matplotlib and numpy for interactive use,
250 250 selecting a particular matplotlib backend and loop integration.
251 251 """
252 252 )
253 253 display_banner = Bool(True, config=True,
254 254 help="Whether to display a banner upon starting IPython."
255 255 )
256 256
257 257 # if there is code of files to run from the cmd line, don't interact
258 258 # unless the --i flag (App.force_interact) is true.
259 259 force_interact = Bool(False, config=True,
260 260 help="""If a command or file is given via the command-line,
261 261 e.g. 'ipython foo.py"""
262 262 )
263 263 def _force_interact_changed(self, name, old, new):
264 264 if new:
265 265 self.interact = True
266 266
267 267 def _file_to_run_changed(self, name, old, new):
268 if new:
269 self.something_to_run = True
268 270 if new and not self.force_interact:
269 271 self.interact = False
270 272 _code_to_run_changed = _file_to_run_changed
271 273 _module_to_run_changed = _file_to_run_changed
272 274
273 275 # internal, not-configurable
274 276 interact=Bool(True)
275
277 something_to_run=Bool(False)
276 278
277 279 def parse_command_line(self, argv=None):
278 280 """override to allow old '-pylab' flag with deprecation warning"""
279 281
280 282 argv = sys.argv[1:] if argv is None else argv
281 283
282 284 if '-pylab' in argv:
283 285 # deprecated `-pylab` given,
284 286 # warn and transform into current syntax
285 287 argv = argv[:] # copy, don't clobber
286 288 idx = argv.index('-pylab')
287 289 warn.warn("`-pylab` flag has been deprecated.\n"
288 290 " Use `--pylab` instead, or `--pylab=foo` to specify a backend.")
289 291 sub = '--pylab'
290 292 if len(argv) > idx+1:
291 293 # check for gui arg, as in '-pylab qt'
292 294 gui = argv[idx+1]
293 295 if gui in ('wx', 'qt', 'qt4', 'gtk', 'auto'):
294 296 sub = '--pylab='+gui
295 297 argv.pop(idx+1)
296 298 argv[idx] = sub
297 299
298 300 return super(TerminalIPythonApp, self).parse_command_line(argv)
299 301
300 302 @catch_config_error
301 303 def initialize(self, argv=None):
302 304 """Do actions after construct, but before starting the app."""
303 305 super(TerminalIPythonApp, self).initialize(argv)
304 306 if self.subapp is not None:
305 307 # don't bother initializing further, starting subapp
306 308 return
307 309 if not self.ignore_old_config:
308 310 check_for_old_config(self.ipython_dir)
309 311 # print self.extra_args
310 if self.extra_args and not self.module_to_run:
312 if self.extra_args and not self.something_to_run:
311 313 self.file_to_run = self.extra_args[0]
312 314 # create the shell
313 315 self.init_shell()
314 316 # and draw the banner
315 317 self.init_banner()
316 318 # Now a variety of things that happen after the banner is printed.
317 319 self.init_gui_pylab()
318 320 self.init_extensions()
319 321 self.init_code()
320 322
321 323 def init_shell(self):
322 324 """initialize the InteractiveShell instance"""
323 325 # I am a little hesitant to put these into InteractiveShell itself.
324 326 # But that might be the place for them
325 327 sys.path.insert(0, '')
326 328
327 329 # Create an InteractiveShell instance.
328 330 # shell.display_banner should always be False for the terminal
329 331 # based app, because we call shell.show_banner() by hand below
330 332 # so the banner shows *before* all extension loading stuff.
331 333 self.shell = TerminalInteractiveShell.instance(config=self.config,
332 334 display_banner=False, profile_dir=self.profile_dir,
333 335 ipython_dir=self.ipython_dir)
334 336 self.shell.configurables.append(self)
335 337
336 338 def init_banner(self):
337 339 """optionally display the banner"""
338 340 if self.display_banner and self.interact:
339 341 self.shell.show_banner()
340 342 # Make sure there is a space below the banner.
341 343 if self.log_level <= logging.INFO: print
342 344
343 345
344 346 def init_gui_pylab(self):
345 347 """Enable GUI event loop integration, taking pylab into account."""
346 348 gui = self.gui
347 349
348 350 # Using `pylab` will also require gui activation, though which toolkit
349 351 # to use may be chosen automatically based on mpl configuration.
350 352 if self.pylab:
351 353 activate = self.shell.enable_pylab
352 354 if self.pylab == 'auto':
353 355 gui = None
354 356 else:
355 357 gui = self.pylab
356 358 else:
357 359 # Enable only GUI integration, no pylab
358 360 activate = inputhook.enable_gui
359 361
360 362 if gui or self.pylab:
361 363 try:
362 364 self.log.info("Enabling GUI event loop integration, "
363 365 "toolkit=%s, pylab=%s" % (gui, self.pylab) )
364 366 if self.pylab:
365 367 activate(gui, import_all=self.pylab_import_all)
366 368 else:
367 369 activate(gui)
368 370 except:
369 371 self.log.warn("Error in enabling GUI event loop integration:")
370 372 self.shell.showtraceback()
371 373
372 374 def start(self):
373 375 if self.subapp is not None:
374 376 return self.subapp.start()
375 377 # perform any prexec steps:
376 378 if self.interact:
377 379 self.log.debug("Starting IPython's mainloop...")
378 380 self.shell.mainloop()
379 381 else:
380 382 self.log.debug("IPython not interactive...")
381 383
382 384
383 385 def load_default_config(ipython_dir=None):
384 386 """Load the default config file from the default ipython_dir.
385 387
386 388 This is useful for embedded shells.
387 389 """
388 390 if ipython_dir is None:
389 391 ipython_dir = get_ipython_dir()
390 392 profile_dir = os.path.join(ipython_dir, 'profile_default')
391 393 cl = PyFileConfigLoader(default_config_file_name, profile_dir)
392 394 try:
393 395 config = cl.load_config()
394 396 except ConfigFileNotFound:
395 397 # no config found
396 398 config = Config()
397 399 return config
398 400
399 401
400 402 def launch_new_instance():
401 403 """Create and run a full blown IPython instance"""
402 404 app = TerminalIPythonApp.instance()
403 405 app.initialize()
404 406 app.start()
405 407
406 408
407 409 if __name__ == '__main__':
408 410 launch_new_instance()
General Comments 0
You need to be logged in to leave comments. Login now