##// END OF EJS Templates
Note use of -- for -i to behave like cpython...
Joel Nothman -
Show More
@@ -1,374 +1,377 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
8 8 # Copyright (c) IPython Development Team.
9 9 # Distributed under the terms of the Modified BSD License.
10 10
11 11 from __future__ import absolute_import
12 12 from __future__ import print_function
13 13
14 14 import logging
15 15 import os
16 16 import sys
17 17
18 18 from traitlets.config.loader import Config
19 19 from traitlets.config.application import boolean_flag, catch_config_error, Application
20 20 from IPython.core import release
21 21 from IPython.core import usage
22 22 from IPython.core.completer import IPCompleter
23 23 from IPython.core.crashhandler import CrashHandler
24 24 from IPython.core.formatters import PlainTextFormatter
25 25 from IPython.core.history import HistoryManager
26 26 from IPython.core.prompts import PromptManager
27 27 from IPython.core.application import (
28 28 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
29 29 )
30 30 from IPython.core.magics import ScriptMagics
31 31 from IPython.core.shellapp import (
32 32 InteractiveShellApp, shell_flags, shell_aliases
33 33 )
34 34 from IPython.extensions.storemagic import StoreMagics
35 35 from IPython.terminal.interactiveshell import TerminalInteractiveShell
36 36 from IPython.utils import warn
37 37 from IPython.paths import get_ipython_dir
38 38 from traitlets import (
39 39 Bool, List, Dict,
40 40 )
41 41
42 42 #-----------------------------------------------------------------------------
43 43 # Globals, utilities and helpers
44 44 #-----------------------------------------------------------------------------
45 45
46 46 _examples = """
47 47 ipython --matplotlib # enable matplotlib integration
48 48 ipython --matplotlib=qt # enable matplotlib integration with qt4 backend
49 49
50 50 ipython --log-level=DEBUG # set logging to DEBUG
51 51 ipython --profile=foo # start with profile foo
52 52
53 53 ipython qtconsole # start the qtconsole GUI application
54 54 ipython help qtconsole # show the help for the qtconsole subcmd
55 55
56 56 ipython console # start the terminal-based console application
57 57 ipython help console # show the help for the console subcmd
58 58
59 59 ipython notebook # start the IPython notebook
60 60 ipython help notebook # show the help for the notebook subcmd
61 61
62 62 ipython profile create foo # create profile foo w/ default config files
63 63 ipython help profile # show the help for the profile subcmd
64 64
65 65 ipython locate # print the path to the IPython directory
66 66 ipython locate profile foo # print the path to the directory for profile `foo`
67 67
68 68 ipython nbconvert # convert notebooks to/from other formats
69 69 """
70 70
71 71 #-----------------------------------------------------------------------------
72 72 # Crash handler for this application
73 73 #-----------------------------------------------------------------------------
74 74
75 75 class IPAppCrashHandler(CrashHandler):
76 76 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
77 77
78 78 def __init__(self, app):
79 79 contact_name = release.author
80 80 contact_email = release.author_email
81 81 bug_tracker = 'https://github.com/ipython/ipython/issues'
82 82 super(IPAppCrashHandler,self).__init__(
83 83 app, contact_name, contact_email, bug_tracker
84 84 )
85 85
86 86 def make_report(self,traceback):
87 87 """Return a string containing a crash report."""
88 88
89 89 sec_sep = self.section_sep
90 90 # Start with parent report
91 91 report = [super(IPAppCrashHandler, self).make_report(traceback)]
92 92 # Add interactive-specific info we may have
93 93 rpt_add = report.append
94 94 try:
95 95 rpt_add(sec_sep+"History of session input:")
96 96 for line in self.app.shell.user_ns['_ih']:
97 97 rpt_add(line)
98 98 rpt_add('\n*** Last line of input (may not be in above history):\n')
99 99 rpt_add(self.app.shell._last_input_line+'\n')
100 100 except:
101 101 pass
102 102
103 103 return ''.join(report)
104 104
105 105 #-----------------------------------------------------------------------------
106 106 # Aliases and Flags
107 107 #-----------------------------------------------------------------------------
108 108 flags = dict(base_flags)
109 109 flags.update(shell_flags)
110 110 frontend_flags = {}
111 111 addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
112 112 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
113 113 'Turn on auto editing of files with syntax errors.',
114 114 'Turn off auto editing of files with syntax errors.'
115 115 )
116 116 addflag('banner', 'TerminalIPythonApp.display_banner',
117 117 "Display a banner upon starting IPython.",
118 118 "Don't display a banner upon starting IPython."
119 119 )
120 120 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
121 121 """Set to confirm when you try to exit IPython with an EOF (Control-D
122 122 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
123 123 you can force a direct exit without any confirmation.""",
124 124 "Don't prompt the user when exiting."
125 125 )
126 126 addflag('term-title', 'TerminalInteractiveShell.term_title',
127 127 "Enable auto setting the terminal title.",
128 128 "Disable auto setting the terminal title."
129 129 )
130 130 classic_config = Config()
131 131 classic_config.InteractiveShell.cache_size = 0
132 132 classic_config.PlainTextFormatter.pprint = False
133 133 classic_config.PromptManager.in_template = '>>> '
134 134 classic_config.PromptManager.in2_template = '... '
135 135 classic_config.PromptManager.out_template = ''
136 136 classic_config.InteractiveShell.separate_in = ''
137 137 classic_config.InteractiveShell.separate_out = ''
138 138 classic_config.InteractiveShell.separate_out2 = ''
139 139 classic_config.InteractiveShell.colors = 'NoColor'
140 140 classic_config.InteractiveShell.xmode = 'Plain'
141 141
142 142 frontend_flags['classic']=(
143 143 classic_config,
144 144 "Gives IPython a similar feel to the classic Python prompt."
145 145 )
146 146 # # log doesn't make so much sense this way anymore
147 147 # paa('--log','-l',
148 148 # action='store_true', dest='InteractiveShell.logstart',
149 149 # help="Start logging to the default log file (./ipython_log.py).")
150 150 #
151 151 # # quick is harder to implement
152 152 frontend_flags['quick']=(
153 153 {'TerminalIPythonApp' : {'quick' : True}},
154 154 "Enable quick startup with no config files."
155 155 )
156 156
157 157 frontend_flags['i'] = (
158 158 {'TerminalIPythonApp' : {'force_interact' : True}},
159 """If running code from the command line, become interactive afterwards."""
159 """If running code from the command line, become interactive afterwards.
160 It is often useful to follow this with `--` to treat remaining flags as
161 script arguments.
162 """
160 163 )
161 164 flags.update(frontend_flags)
162 165
163 166 aliases = dict(base_aliases)
164 167 aliases.update(shell_aliases)
165 168
166 169 #-----------------------------------------------------------------------------
167 170 # Main classes and functions
168 171 #-----------------------------------------------------------------------------
169 172
170 173
171 174 class LocateIPythonApp(BaseIPythonApplication):
172 175 description = """print the path to the IPython dir"""
173 176 subcommands = Dict(dict(
174 177 profile=('IPython.core.profileapp.ProfileLocate',
175 178 "print the path to an IPython profile directory",
176 179 ),
177 180 ))
178 181 def start(self):
179 182 if self.subapp is not None:
180 183 return self.subapp.start()
181 184 else:
182 185 print(self.ipython_dir)
183 186
184 187
185 188 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
186 189 name = u'ipython'
187 190 description = usage.cl_usage
188 191 crash_handler_class = IPAppCrashHandler
189 192 examples = _examples
190 193
191 194 flags = Dict(flags)
192 195 aliases = Dict(aliases)
193 196 classes = List()
194 197 def _classes_default(self):
195 198 """This has to be in a method, for TerminalIPythonApp to be available."""
196 199 return [
197 200 InteractiveShellApp, # ShellApp comes before TerminalApp, because
198 201 self.__class__, # it will also affect subclasses (e.g. QtConsole)
199 202 TerminalInteractiveShell,
200 203 PromptManager,
201 204 HistoryManager,
202 205 ProfileDir,
203 206 PlainTextFormatter,
204 207 IPCompleter,
205 208 ScriptMagics,
206 209 StoreMagics,
207 210 ]
208 211
209 212 subcommands = dict(
210 213 qtconsole=('qtconsole.qtconsoleapp.JupyterQtConsoleApp',
211 214 """DEPRECATD: Launch the Jupyter Qt Console."""
212 215 ),
213 216 notebook=('notebook.notebookapp.NotebookApp',
214 217 """DEPRECATED: Launch the Jupyter HTML Notebook Server."""
215 218 ),
216 219 profile = ("IPython.core.profileapp.ProfileApp",
217 220 "Create and manage IPython profiles."
218 221 ),
219 222 kernel = ("ipykernel.kernelapp.IPKernelApp",
220 223 "Start a kernel without an attached frontend."
221 224 ),
222 225 console=('jupyter_console.app.ZMQTerminalIPythonApp',
223 226 """DEPRECATED: Launch the Jupyter terminal-based Console."""
224 227 ),
225 228 locate=('IPython.terminal.ipapp.LocateIPythonApp',
226 229 LocateIPythonApp.description
227 230 ),
228 231 history=('IPython.core.historyapp.HistoryApp',
229 232 "Manage the IPython history database."
230 233 ),
231 234 nbconvert=('nbconvert.nbconvertapp.NbConvertApp',
232 235 "DEPRECATED: Convert notebooks to/from other formats."
233 236 ),
234 237 trust=('nbformat.sign.TrustNotebookApp',
235 238 "DEPRECATED: Sign notebooks to trust their potentially unsafe contents at load."
236 239 ),
237 240 kernelspec=('jupyter_client.kernelspecapp.KernelSpecApp',
238 241 "DEPRECATED: Manage Jupyter kernel specifications."
239 242 ),
240 243 )
241 244 subcommands['install-nbextension'] = (
242 245 "notebook.nbextensions.InstallNBExtensionApp",
243 246 "DEPRECATED: Install Jupyter notebook extension files"
244 247 )
245 248
246 249 # *do* autocreate requested profile, but don't create the config file.
247 250 auto_create=Bool(True)
248 251 # configurables
249 252 quick = Bool(False, config=True,
250 253 help="""Start IPython quickly by skipping the loading of config files."""
251 254 )
252 255 def _quick_changed(self, name, old, new):
253 256 if new:
254 257 self.load_config_file = lambda *a, **kw: None
255 258
256 259 display_banner = Bool(True, config=True,
257 260 help="Whether to display a banner upon starting IPython."
258 261 )
259 262
260 263 # if there is code of files to run from the cmd line, don't interact
261 264 # unless the --i flag (App.force_interact) is true.
262 265 force_interact = Bool(False, config=True,
263 266 help="""If a command or file is given via the command-line,
264 267 e.g. 'ipython foo.py', start an interactive shell after executing the
265 268 file or command."""
266 269 )
267 270 def _force_interact_changed(self, name, old, new):
268 271 if new:
269 272 self.interact = True
270 273
271 274 def _file_to_run_changed(self, name, old, new):
272 275 if new:
273 276 self.something_to_run = True
274 277 if new and not self.force_interact:
275 278 self.interact = False
276 279 _code_to_run_changed = _file_to_run_changed
277 280 _module_to_run_changed = _file_to_run_changed
278 281
279 282 # internal, not-configurable
280 283 interact=Bool(True)
281 284 something_to_run=Bool(False)
282 285
283 286 def parse_command_line(self, argv=None):
284 287 """override to allow old '-pylab' flag with deprecation warning"""
285 288
286 289 argv = sys.argv[1:] if argv is None else argv
287 290
288 291 if '-pylab' in argv:
289 292 # deprecated `-pylab` given,
290 293 # warn and transform into current syntax
291 294 argv = argv[:] # copy, don't clobber
292 295 idx = argv.index('-pylab')
293 296 warn.warn("`-pylab` flag has been deprecated.\n"
294 297 " Use `--matplotlib <backend>` and import pylab manually.")
295 298 argv[idx] = '--pylab'
296 299
297 300 return super(TerminalIPythonApp, self).parse_command_line(argv)
298 301
299 302 @catch_config_error
300 303 def initialize(self, argv=None):
301 304 """Do actions after construct, but before starting the app."""
302 305 super(TerminalIPythonApp, self).initialize(argv)
303 306 if self.subapp is not None:
304 307 # don't bother initializing further, starting subapp
305 308 return
306 309 # print self.extra_args
307 310 if self.extra_args and not self.something_to_run:
308 311 self.file_to_run = self.extra_args[0]
309 312 self.init_path()
310 313 # create the shell
311 314 self.init_shell()
312 315 # and draw the banner
313 316 self.init_banner()
314 317 # Now a variety of things that happen after the banner is printed.
315 318 self.init_gui_pylab()
316 319 self.init_extensions()
317 320 self.init_code()
318 321
319 322 def init_shell(self):
320 323 """initialize the InteractiveShell instance"""
321 324 # Create an InteractiveShell instance.
322 325 # shell.display_banner should always be False for the terminal
323 326 # based app, because we call shell.show_banner() by hand below
324 327 # so the banner shows *before* all extension loading stuff.
325 328 self.shell = TerminalInteractiveShell.instance(parent=self,
326 329 display_banner=False, profile_dir=self.profile_dir,
327 330 ipython_dir=self.ipython_dir, user_ns=self.user_ns)
328 331 self.shell.configurables.append(self)
329 332
330 333 def init_banner(self):
331 334 """optionally display the banner"""
332 335 if self.display_banner and self.interact:
333 336 self.shell.show_banner()
334 337 # Make sure there is a space below the banner.
335 338 if self.log_level <= logging.INFO: print()
336 339
337 340 def _pylab_changed(self, name, old, new):
338 341 """Replace --pylab='inline' with --pylab='auto'"""
339 342 if new == 'inline':
340 343 warn.warn("'inline' not available as pylab backend, "
341 344 "using 'auto' instead.")
342 345 self.pylab = 'auto'
343 346
344 347 def start(self):
345 348 if self.subapp is not None:
346 349 return self.subapp.start()
347 350 # perform any prexec steps:
348 351 if self.interact:
349 352 self.log.debug("Starting IPython's mainloop...")
350 353 self.shell.mainloop()
351 354 else:
352 355 self.log.debug("IPython not interactive...")
353 356
354 357 def load_default_config(ipython_dir=None):
355 358 """Load the default config file from the default ipython_dir.
356 359
357 360 This is useful for embedded shells.
358 361 """
359 362 if ipython_dir is None:
360 363 ipython_dir = get_ipython_dir()
361 364
362 365 profile_dir = os.path.join(ipython_dir, 'profile_default')
363 366
364 367 config = Config()
365 368 for cf in Application._load_config_files("ipython_config", path=profile_dir):
366 369 config.update(cf)
367 370
368 371 return config
369 372
370 373 launch_new_instance = TerminalIPythonApp.launch_instance
371 374
372 375
373 376 if __name__ == '__main__':
374 377 launch_new_instance()
General Comments 0
You need to be logged in to leave comments. Login now