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