##// END OF EJS Templates
Ported the IPython Sphinx directive to 0.11....
Fernando Perez -
Show More
This diff has been collapsed as it changes many lines, (641 lines changed) Show them Hide them
@@ -0,0 +1,641 b''
1 # -*- coding: utf-8 -*-
2 """Sphinx directive to support embedded IPython code.
3
4 This directive allows pasting of entire interactive IPython sessions, prompts
5 and all, and their code will actually get re-executed at doc build time, with
6 all prompts renumbered sequentially.
7
8 To enable this directive, simply list it in your Sphinx ``conf.py`` file
9 (making sure the directory where you placed it is visible to sphinx, as is
10 needed for all Sphinx directives).
11
12 By default this directive assumes that your prompts are unchanged IPython ones,
13 but this can be customized. For example, the following code in your Sphinx
14 config file will configure this directive for the following input/output
15 prompts ``Yade [1]:`` and ``-> [1]:``::
16
17 import ipython_directive as id
18 id.rgxin =re.compile(r'(?:In |Yade )\[(\d+)\]:\s?(.*)\s*')
19 id.rgxout=re.compile(r'(?:Out| -> )\[(\d+)\]:\s?(.*)\s*')
20 id.fmtin ='Yade [%d]:'
21 id.fmtout=' -> [%d]:'
22
23 from IPython import Config
24 id.CONFIG = Config(
25 prompt_in1="Yade [\#]:",
26 prompt_in2=" .\D..",
27 prompt_out=" -> [\#]:"
28 )
29 id.reconfig_shell()
30
31 import ipython_console_highlighting as ich
32 ich.IPythonConsoleLexer.input_prompt=
33 re.compile("(Yade \[[0-9]+\]: )|( \.\.\.+:)")
34 ich.IPythonConsoleLexer.output_prompt=
35 re.compile("(( -> )|(Out)\[[0-9]+\]: )|( \.\.\.+:)")
36 ich.IPythonConsoleLexer.continue_prompt=re.compile(" \.\.\.+:")
37
38
39 ToDo
40 ----
41
42 - Turn the ad-hoc test() function into a real test suite.
43 - Break up ipython-specific functionality from matplotlib stuff into better
44 separated code.
45 - Make sure %bookmarks used internally are removed on exit.
46
47
48 Authors
49 -------
50
51 - John D Hunter: orignal author.
52 - Fernando Perez: refactoring, documentation, cleanups, port to 0.11.
53 - VΓ‘clavΕ milauer <eudoxos-AT-arcig.cz>: Prompt generalizations.
54 """
55
56 #-----------------------------------------------------------------------------
57 # Imports
58 #-----------------------------------------------------------------------------
59
60 # Stdlib
61 import cStringIO
62 import imp
63 import os
64 import re
65 import shutil
66 import sys
67 import warnings
68
69 # To keep compatibility with various python versions
70 try:
71 from hashlib import md5
72 except ImportError:
73 from md5 import md5
74
75 # Third-party
76 import matplotlib
77 import sphinx
78 from docutils.parsers.rst import directives
79
80 matplotlib.use('Agg')
81
82 # Our own
83 from IPython import Config, IPythonApp
84 from IPython.utils.genutils import Term, Tee
85
86 #-----------------------------------------------------------------------------
87 # Globals
88 #-----------------------------------------------------------------------------
89
90 sphinx_version = sphinx.__version__.split(".")
91 # The split is necessary for sphinx beta versions where the string is
92 # '6b1'
93 sphinx_version = tuple([int(re.split('[a-z]', x)[0])
94 for x in sphinx_version[:2]])
95
96 COMMENT, INPUT, OUTPUT = range(3)
97 CONFIG = Config()
98 rgxin = re.compile('In \[(\d+)\]:\s?(.*)\s*')
99 rgxout = re.compile('Out\[(\d+)\]:\s?(.*)\s*')
100 fmtin = 'In [%d]:'
101 fmtout = 'Out[%d]:'
102
103 #-----------------------------------------------------------------------------
104 # Functions and class declarations
105 #-----------------------------------------------------------------------------
106 def block_parser(part):
107 """
108 part is a string of ipython text, comprised of at most one
109 input, one ouput, comments, and blank lines. The block parser
110 parses the text into a list of::
111
112 blocks = [ (TOKEN0, data0), (TOKEN1, data1), ...]
113
114 where TOKEN is one of [COMMENT | INPUT | OUTPUT ] and
115 data is, depending on the type of token::
116
117 COMMENT : the comment string
118
119 INPUT: the (DECORATOR, INPUT_LINE, REST) where
120 DECORATOR: the input decorator (or None)
121 INPUT_LINE: the input as string (possibly multi-line)
122 REST : any stdout generated by the input line (not OUTPUT)
123
124
125 OUTPUT: the output string, possibly multi-line
126 """
127
128 block = []
129 lines = part.split('\n')
130 N = len(lines)
131 i = 0
132 decorator = None
133 while 1:
134
135 if i==N:
136 # nothing left to parse -- the last line
137 break
138
139 line = lines[i]
140 i += 1
141 line_stripped = line.strip()
142 if line_stripped.startswith('#'):
143 block.append((COMMENT, line))
144 continue
145
146 if line_stripped.startswith('@'):
147 # we're assuming at most one decorator -- may need to
148 # rethink
149 decorator = line_stripped
150 continue
151
152 # does this look like an input line?
153 matchin = rgxin.match(line)
154 if matchin:
155 lineno, inputline = int(matchin.group(1)), matchin.group(2)
156
157 # the ....: continuation string
158 continuation = ' %s:'%''.join(['.']*(len(str(lineno))+2))
159 Nc = len(continuation)
160 # input lines can continue on for more than one line, if
161 # we have a '\' line continuation char or a function call
162 # echo line 'print'. The input line can only be
163 # terminated by the end of the block or an output line, so
164 # we parse out the rest of the input line if it is
165 # multiline as well as any echo text
166
167 rest = []
168 while i<N:
169
170 # look ahead; if the next line is blank, or a comment, or
171 # an output line, we're done
172
173 nextline = lines[i]
174 matchout = rgxout.match(nextline)
175 #print "nextline=%s, continuation=%s, starts=%s"%(nextline, continuation, nextline.startswith(continuation))
176 if matchout or nextline.startswith('#'):
177 break
178 elif nextline.startswith(continuation):
179 inputline += '\n' + nextline[Nc:]
180 else:
181 rest.append(nextline)
182 i+= 1
183
184 block.append((INPUT, (decorator, inputline, '\n'.join(rest))))
185 continue
186
187 # if it looks like an output line grab all the text to the end
188 # of the block
189 matchout = rgxout.match(line)
190 if matchout:
191 lineno, output = int(matchout.group(1)), matchout.group(2)
192 if i<N-1:
193 output = '\n'.join([output] + lines[i:])
194
195 block.append((OUTPUT, output))
196 break
197
198 return block
199
200
201 class EmbeddedSphinxShell(object):
202 """An embedded IPython instance to run inside Sphinx"""
203
204 def __init__(self):
205
206 self.cout = cStringIO.StringIO()
207 Term.cout = self.cout
208 Term.cerr = self.cout
209
210 # For debugging, so we can see normal output, use this:
211 #Term.cout = genutils.Tee(self.cout, channel='stdout') # dbg
212 #Term.cerr = genutils.Tee(self.cout, channel='stderr') # dbg
213
214 # Create config object for IPython
215 config = Config()
216 config.Global.display_banner = False
217 config.Global.exec_lines = ['import numpy as np',
218 'from pylab import *'
219 ]
220 config.InteractiveShell.autocall = False
221 config.InteractiveShell.autoindent = False
222 config.InteractiveShell.colors = 'NoColor'
223
224 # Merge global config which can be used to override.
225 config._merge(CONFIG)
226
227 # Create and initialize ipython, but don't start its mainloop
228 IP = IPythonApp(override_config=config)
229 IP.initialize()
230
231 # Store a few parts of IPython we'll need.
232 self.IP = IP.shell
233 self.user_ns = self.IP.user_ns
234 self.user_global_ns = self.IP.user_global_ns
235
236 self.input = ''
237 self.output = ''
238
239 self.is_verbatim = False
240 self.is_doctest = False
241 self.is_suppress = False
242
243 # on the first call to the savefig decorator, we'll import
244 # pyplot as plt so we can make a call to the plt.gcf().savefig
245 self._pyplot_imported = False
246
247 # we need bookmark the current dir first so we can save
248 # relative to it
249 self.process_input_line('bookmark ipy_basedir')
250 self.cout.seek(0)
251 self.cout.truncate(0)
252
253 def process_input_line(self, line):
254 """process the input, capturing stdout"""
255 #print "input='%s'"%self.input
256 stdout = sys.stdout
257 try:
258 sys.stdout = self.cout
259 self.IP.push_line(line)
260 finally:
261 sys.stdout = stdout
262
263 # Callbacks for each type of token
264 def process_input(self, data, input_prompt, lineno):
265 """Process data block for INPUT token."""
266 decorator, input, rest = data
267 image_file = None
268 #print 'INPUT:', data # dbg
269 is_verbatim = decorator=='@verbatim' or self.is_verbatim
270 is_doctest = decorator=='@doctest' or self.is_doctest
271 is_suppress = decorator=='@suppress' or self.is_suppress
272 is_savefig = decorator is not None and \
273 decorator.startswith('@savefig')
274
275 input_lines = input.split('\n')
276
277 continuation = ' %s:'%''.join(['.']*(len(str(lineno))+2))
278 Nc = len(continuation)
279
280 if is_savefig:
281 saveargs = decorator.split(' ')
282 filename = saveargs[1]
283 outfile = os.path.join('_static/%s'%filename)
284 # build out an image directive like
285 # .. image:: somefile.png
286 # :width 4in
287 #
288 # from an input like
289 # savefig somefile.png width=4in
290 imagerows = ['.. image:: %s'%outfile]
291
292 for kwarg in saveargs[2:]:
293 arg, val = kwarg.split('=')
294 arg = arg.strip()
295 val = val.strip()
296 imagerows.append(' :%s: %s'%(arg, val))
297
298 image_file = outfile
299 image_directive = '\n'.join(imagerows)
300
301 # TODO: can we get "rest" from ipython
302 #self.process_input_line('\n'.join(input_lines))
303
304 ret = []
305 is_semicolon = False
306
307 for i, line in enumerate(input_lines):
308 if line.endswith(';'):
309 is_semicolon = True
310
311 if i==0:
312 # process the first input line
313 if is_verbatim:
314 self.process_input_line('')
315 else:
316 # only submit the line in non-verbatim mode
317 self.process_input_line(line)
318 formatted_line = '%s %s'%(input_prompt, line)
319 else:
320 # process a continuation line
321 if not is_verbatim:
322 self.process_input_line(line)
323
324 formatted_line = '%s %s'%(continuation, line)
325
326 if not is_suppress:
327 ret.append(formatted_line)
328
329 if not is_suppress:
330 if len(rest.strip()):
331 if is_verbatim:
332 # the "rest" is the standard output of the
333 # input, which needs to be added in
334 # verbatim mode
335 ret.append(rest)
336
337 self.cout.seek(0)
338 output = self.cout.read()
339 if not is_suppress and not is_semicolon:
340 ret.append(output)
341
342 self.cout.truncate(0)
343 return ret, input_lines, output, is_doctest, image_file
344 #print 'OUTPUT', output # dbg
345
346 def process_output(self, data, output_prompt,
347 input_lines, output, is_doctest, image_file):
348 """Process data block for OUTPUT token."""
349 if is_doctest:
350 submitted = data.strip()
351 found = output
352 if found is not None:
353 found = found.strip()
354
355 # XXX - fperez: in 0.11, 'output' never comes with the prompt
356 # in it, just the actual output text. So I think all this code
357 # can be nuked...
358 ## ind = found.find(output_prompt)
359 ## if ind<0:
360 ## e='output prompt="%s" does not match out line=%s' % \
361 ## (output_prompt, found)
362 ## raise RuntimeError(e)
363 ## found = found[len(output_prompt):].strip()
364
365 if found!=submitted:
366 e = ('doctest failure for input_lines="%s" with '
367 'found_output="%s" and submitted output="%s"' %
368 (input_lines, found, submitted) )
369 raise RuntimeError(e)
370 #print 'doctest PASSED for input_lines="%s" with found_output="%s" and submitted output="%s"'%(input_lines, found, submitted)
371
372 def process_comment(self, data):
373 """Process data block for COMMENT token."""
374 if not self.is_suppress:
375 return [data]
376
377 def process_block(self, block):
378 """
379 process block from the block_parser and return a list of processed lines
380 """
381
382 ret = []
383 output = None
384 input_lines = None
385
386 m = rgxin.match(str(self.IP.outputcache.prompt1).strip())
387 lineno = int(m.group(1))
388
389 input_prompt = fmtin%lineno
390 output_prompt = fmtout%lineno
391 image_file = None
392 image_directive = None
393 # XXX - This needs a second refactor. There's too much state being
394 # held globally, which makes for a very awkward interface and large,
395 # hard to test functions. I've already broken this up at least into
396 # three separate processors to isolate the logic better, but this only
397 # serves to highlight the coupling. Next we need to clean it up...
398 for token, data in block:
399 if token==COMMENT:
400 out_data = self.process_comment(data)
401 elif token==INPUT:
402 out_data, input_lines, output, is_doctest, image_file= \
403 self.process_input(data, input_prompt, lineno)
404 elif token==OUTPUT:
405 out_data = \
406 self.process_output(data, output_prompt,
407 input_lines, output, is_doctest,
408 image_file)
409 if out_data:
410 ret.extend(out_data)
411
412 if image_file is not None:
413 self.ensure_pyplot()
414 command = 'plt.gcf().savefig("%s")'%image_file
415 print 'SAVEFIG', command # dbg
416 self.process_input_line('bookmark ipy_thisdir')
417 self.process_input_line('cd -b ipy_basedir')
418 self.process_input_line(command)
419 self.process_input_line('cd -b ipy_thisdir')
420 self.cout.seek(0)
421 self.cout.truncate(0)
422 return ret, image_directive
423
424 def ensure_pyplot(self):
425 if self._pyplot_imported:
426 return
427 self.process_input_line('import matplotlib.pyplot as plt')
428
429 # A global instance used below. XXX: not sure why this can't be created inside
430 # ipython_directive itself.
431 shell = EmbeddedSphinxShell()
432
433 def reconfig_shell():
434 """Called after setting module-level variables to re-instantiate
435 with the set values (since shell is instantiated first at import-time
436 when module variables have default values)"""
437 global shell
438 shell = EmbeddedSphinxShell()
439
440
441 def ipython_directive(name, arguments, options, content, lineno,
442 content_offset, block_text, state, state_machine,
443 ):
444
445 debug = ipython_directive.DEBUG
446 shell.is_suppress = options.has_key('suppress')
447 shell.is_doctest = options.has_key('doctest')
448 shell.is_verbatim = options.has_key('verbatim')
449
450 #print 'ipy', shell.is_suppress, options
451 parts = '\n'.join(content).split('\n\n')
452 lines = ['.. sourcecode:: ipython', '']
453
454 figures = []
455 for part in parts:
456 block = block_parser(part)
457
458 if len(block):
459 rows, figure = shell.process_block(block)
460 for row in rows:
461 lines.extend([' %s'%line for line in row.split('\n')])
462
463 if figure is not None:
464 figures.append(figure)
465
466 for figure in figures:
467 lines.append('')
468 lines.extend(figure.split('\n'))
469 lines.append('')
470
471 #print lines
472 if len(lines)>2:
473 if debug:
474 print '\n'.join(lines)
475 else:
476 #print 'INSERTING %d lines'%len(lines)
477 state_machine.insert_input(
478 lines, state_machine.input_lines.source(0))
479
480 return []
481
482 ipython_directive.DEBUG = False
483 ipython_directive.DEBUG = True # dbg
484
485 # Enable as a proper Sphinx directive
486 def setup(app):
487 setup.app = app
488 options = {'suppress': directives.flag,
489 'doctest': directives.flag,
490 'verbatim': directives.flag,
491 }
492
493 app.add_directive('ipython', ipython_directive, True, (0, 2, 0), **options)
494
495
496 # Simple smoke test, needs to be converted to a proper automatic test.
497 def test():
498
499 examples = [
500 r"""
501 In [9]: pwd
502 Out[9]: '/home/jdhunter/py4science/book'
503
504 In [10]: cd bookdata/
505 /home/jdhunter/py4science/book/bookdata
506
507 In [2]: from pylab import *
508
509 In [2]: ion()
510
511 In [3]: im = imread('stinkbug.png')
512
513 @savefig mystinkbug.png width=4in
514 In [4]: imshow(im)
515 Out[4]: <matplotlib.image.AxesImage object at 0x39ea850>
516
517 """,
518 r"""
519
520 In [1]: x = 'hello world'
521
522 # string methods can be
523 # used to alter the string
524 @doctest
525 In [2]: x.upper()
526 Out[2]: 'HELLO WORLD'
527
528 @verbatim
529 In [3]: x.st<TAB>
530 x.startswith x.strip
531 """,
532 r"""
533
534 In [130]: url = 'http://ichart.finance.yahoo.com/table.csv?s=CROX\
535 .....: &d=9&e=22&f=2009&g=d&a=1&br=8&c=2006&ignore=.csv'
536
537 In [131]: print url.split('&')
538 ['http://ichart.finance.yahoo.com/table.csv?s=CROX', 'd=9', 'e=22', 'f=2009', 'g=d', 'a=1', 'b=8', 'c=2006', 'ignore=.csv']
539
540 In [60]: import urllib
541
542 """,
543 r"""\
544
545 In [133]: import numpy.random
546
547 @suppress
548 In [134]: numpy.random.seed(2358)
549
550 @doctest
551 In [135]: np.random.rand(10,2)
552 Out[135]:
553 array([[ 0.64524308, 0.59943846],
554 [ 0.47102322, 0.8715456 ],
555 [ 0.29370834, 0.74776844],
556 [ 0.99539577, 0.1313423 ],
557 [ 0.16250302, 0.21103583],
558 [ 0.81626524, 0.1312433 ],
559 [ 0.67338089, 0.72302393],
560 [ 0.7566368 , 0.07033696],
561 [ 0.22591016, 0.77731835],
562 [ 0.0072729 , 0.34273127]])
563
564 """,
565
566 r"""
567 In [106]: print x
568 jdh
569
570 In [109]: for i in range(10):
571 .....: print i
572 .....:
573 .....:
574 0
575 1
576 2
577 3
578 4
579 5
580 6
581 7
582 8
583 9
584 """,
585
586 r"""
587
588 In [144]: from pylab import *
589
590 In [145]: ion()
591
592 # use a semicolon to suppress the output
593 @savefig test_hist.png width=4in
594 In [151]: hist(np.random.randn(10000), 100);
595
596
597 @savefig test_plot.png width=4in
598 In [151]: plot(np.random.randn(10000), 'o');
599 """,
600
601 r"""
602 # use a semicolon to suppress the output
603 In [151]: plt.clf()
604
605 @savefig plot_simple.png width=4in
606 In [151]: plot([1,2,3])
607
608 @savefig hist_simple.png width=4in
609 In [151]: hist(np.random.randn(10000), 100);
610
611 """,
612 r"""
613 # update the current fig
614 In [151]: ylabel('number')
615
616 In [152]: title('normal distribution')
617
618
619 @savefig hist_with_text.png
620 In [153]: grid(True)
621
622 """,
623 ]
624
625 #ipython_directive.DEBUG = True # dbg
626 #options = dict(suppress=True) # dbg
627 options = dict()
628 for example in examples:
629 content = example.split('\n')
630 ipython_directive('debug', arguments=None, options=options,
631 content=content, lineno=0,
632 content_offset=None, block_text=None,
633 state=None, state_machine=None,
634 )
635
636 # Run test suite as a script
637 if __name__=='__main__':
638 if not os.path.isdir('_static'):
639 os.mkdir('_static')
640 test()
641 print 'All OK? Check figures in _static/'
@@ -1,63 +1,67 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 """
4 4 IPython.
5 5
6 6 IPython is a set of tools for interactive and exploratory computing in Python.
7 7 """
8 8
9 9 #-----------------------------------------------------------------------------
10 10 # Copyright (C) 2008-2009 The IPython Development Team
11 11 #
12 12 # Distributed under the terms of the BSD License. The full license is in
13 13 # the file COPYING, distributed as part of this software.
14 14 #-----------------------------------------------------------------------------
15 15
16 16 #-----------------------------------------------------------------------------
17 17 # Imports
18 18 #-----------------------------------------------------------------------------
19 from __future__ import absolute_import
19 20
20 21 import os
21 22 import sys
22 from IPython.core import release
23 23
24 24 #-----------------------------------------------------------------------------
25 25 # Setup everything
26 26 #-----------------------------------------------------------------------------
27 27
28 28 if sys.version[0:3] < '2.5':
29 29 raise ImportError('Python Version 2.5 or above is required for IPython.')
30 30
31 31
32 32 # Make it easy to import extensions - they are always directly on pythonpath.
33 33 # Therefore, non-IPython modules can be added to extensions directory
34 34 sys.path.append(os.path.join(os.path.dirname(__file__), "extensions"))
35 35
36 36 #-----------------------------------------------------------------------------
37 37 # Setup the top level names
38 38 #-----------------------------------------------------------------------------
39 39
40 40 # In some cases, these are causing circular imports.
41 from IPython.core.iplib import InteractiveShell
42 from IPython.core.embed import embed
43 from IPython.core.error import TryNext
44 from IPython.testing import test
41 from .config.loader import Config
42 from .core import release
43 from .core.application import Application
44 from .core.ipapp import IPythonApp
45 from .core.embed import embed
46 from .core.error import TryNext
47 from .core.iplib import InteractiveShell
48 from .testing import test
45 49
46 from IPython.lib import (
50 from .lib import (
47 51 enable_wx, disable_wx,
48 52 enable_gtk, disable_gtk,
49 53 enable_qt4, disable_qt4,
50 54 enable_tk, disable_tk,
51 55 set_inputhook, clear_inputhook,
52 56 current_gui, spin,
53 57 appstart_qt4, appstart_wx,
54 58 appstart_gtk, appstart_tk
55 59 )
56 60
57 61 # Release data
58 62 __author__ = ''
59 63 for author, email in release.authors.values():
60 64 __author__ += author + ' <' + email + '>\n'
61 65 __license__ = release.license
62 66 __version__ = release.version
63 67 __revision__ = release.revision
@@ -1,417 +1,490 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 """
4 4 An application for IPython.
5 5
6 6 All top-level applications should use the classes in this module for
7 7 handling configuration and creating componenets.
8 8
9 9 The job of an :class:`Application` is to create the master configuration
10 10 object and then create the components, passing the config to them.
11 11
12 12 Authors:
13 13
14 14 * Brian Granger
15 15 * Fernando Perez
16 16
17 17 Notes
18 18 -----
19 19 """
20 20
21 21 #-----------------------------------------------------------------------------
22 22 # Copyright (C) 2008-2009 The IPython Development Team
23 23 #
24 24 # Distributed under the terms of the BSD License. The full license is in
25 25 # the file COPYING, distributed as part of this software.
26 26 #-----------------------------------------------------------------------------
27 27
28 28 #-----------------------------------------------------------------------------
29 29 # Imports
30 30 #-----------------------------------------------------------------------------
31 31
32 32 import logging
33 33 import os
34 34 import sys
35 35
36 36 from IPython.core import release, crashhandler
37 37 from IPython.utils.genutils import get_ipython_dir, get_ipython_package_dir
38 38 from IPython.config.loader import (
39 39 PyFileConfigLoader,
40 40 ArgParseConfigLoader,
41 41 Config,
42 42 )
43 43
44 44 #-----------------------------------------------------------------------------
45 45 # Classes and functions
46 46 #-----------------------------------------------------------------------------
47 47
48 48 class ApplicationError(Exception):
49 49 pass
50 50
51 51
52 52 app_cl_args = (
53 53 (('--ipython-dir', ), dict(
54 54 dest='Global.ipython_dir',type=unicode,
55 55 help=
56 56 """Set to override default location of the IPython directory
57 57 IPYTHON_DIR, stored as Global.ipython_dir. This can also be specified
58 58 through the environment variable IPYTHON_DIR.""",
59 59 metavar='Global.ipython_dir') ),
60 60 (('-p', '--profile',), dict(
61 61 dest='Global.profile',type=unicode,
62 62 help=
63 63 """The string name of the ipython profile to be used. Assume that your
64 64 config file is ipython_config-<name>.py (looks in current dir first,
65 65 then in IPYTHON_DIR). This is a quick way to keep and load multiple
66 66 config files for different tasks, especially if include your basic one
67 67 in your more specialized ones. You can keep a basic
68 68 IPYTHON_DIR/ipython_config.py file and then have other 'profiles' which
69 69 include this one and load extra things for particular tasks.""",
70 70 metavar='Global.profile') ),
71 71 (('--log-level',), dict(
72 72 dest="Global.log_level",type=int,
73 73 help='Set the log level (0,10,20,30,40,50). Default is 30.',
74 74 metavar='Global.log_level')),
75 75 (('--config-file',), dict(
76 76 dest='Global.config_file',type=unicode,
77 77 help=
78 78 """Set the config file name to override default. Normally IPython
79 79 loads ipython_config.py (from current directory) or
80 80 IPYTHON_DIR/ipython_config.py. If the loading of your config file
81 81 fails, IPython starts with a bare bones configuration (no modules
82 82 loaded at all).""",
83 83 metavar='Global.config_file')),
84 84 )
85 85
86 86 class Application(object):
87 """Load a config, construct components and set them running."""
87 """Load a config, construct components and set them running.
88
89 The configuration of an application can be done via four different Config
90 objects, which are loaded and ultimately merged into a single one used from
91 that point on by the app. These are:
92
93 1. default_config: internal defaults, implemented in code.
94 2. file_config: read from the filesystem.
95 3. command_line_config: read from the system's command line flags.
96 4. constructor_config: passed parametrically to the constructor.
97
98 During initialization, 3 is actually read before 2, since at the
99 command-line one may override the location of the file to be read. But the
100 above is the order in which the merge is made.
101
102 There is a final config object can be created and passed to the
103 constructor: override_config. If it exists, this completely overrides the
104 configs 2-4 above (the default is still used to ensure that all needed
105 fields at least are created). This makes it easier to create
106 parametrically (e.g. in testing or sphinx plugins) objects with a known
107 configuration, that are unaffected by whatever arguments may be present in
108 sys.argv or files in the user's various directories.
109 """
88 110
89 111 name = u'ipython'
90 112 description = 'IPython: an enhanced interactive Python shell.'
91 113 #: usage message printed by argparse. If None, auto-generate
92 114 usage = None
93 115 config_file_name = u'ipython_config.py'
94 # Track the default and actual separately because some messages are
95 # only printed if we aren't using the default.
116 #: Track the default and actual separately because some messages are
117 #: only printed if we aren't using the default.
96 118 default_config_file_name = config_file_name
97 119 default_log_level = logging.WARN
98 # Set by --profile option
120 #: Set by --profile option
99 121 profile_name = None
100 122 #: User's ipython directory, typically ~/.ipython/
101 123 ipython_dir = None
124 #: internal defaults, implemented in code.
125 default_config = None
126 #: read from the filesystem
127 file_config = None
128 #: read from the system's command line flags
129 command_line_config = None
130 #: passed parametrically to the constructor.
131 constructor_config = None
132 #: final override, if given supercedes file/command/constructor configs
133 override_config = None
102 134 #: A reference to the argv to be used (typically ends up being sys.argv[1:])
103 135 argv = None
104 136 #: Default command line arguments. Subclasses should create a new tuple
105 137 #: that *includes* these.
106 138 cl_arguments = app_cl_args
107 139
140 #: extra arguments computed by the command-line loader
141 extra_args = None
142
108 143 # Private attributes
109 144 _exiting = False
110 145 _initialized = False
111 146
112 147 # Class choices for things that will be instantiated at runtime.
113 148 _CrashHandler = crashhandler.CrashHandler
114 149
115 def __init__(self, argv=None):
150 def __init__(self, argv=None, constructor_config=None, override_config=None):
116 151 self.argv = sys.argv[1:] if argv is None else argv
152 self.constructor_config = constructor_config
153 self.override_config = override_config
117 154 self.init_logger()
118 155
119 156 def init_logger(self):
120 157 self.log = logging.getLogger(self.__class__.__name__)
121 158 # This is used as the default until the command line arguments are read.
122 159 self.log.setLevel(self.default_log_level)
123 160 self._log_handler = logging.StreamHandler()
124 161 self._log_formatter = logging.Formatter("[%(name)s] %(message)s")
125 162 self._log_handler.setFormatter(self._log_formatter)
126 163 self.log.addHandler(self._log_handler)
127 164
128 165 def _set_log_level(self, level):
129 166 self.log.setLevel(level)
130 167
131 168 def _get_log_level(self):
132 169 return self.log.level
133 170
134 171 log_level = property(_get_log_level, _set_log_level)
135 172
136 173 def initialize(self):
137 """Start the application."""
174 """Initialize the application.
175
176 Loads all configuration information and sets all application state, but
177 does not start any relevant processing (typically some kind of event
178 loop).
179
180 Once this method has been called, the application is flagged as
181 initialized and the method becomes a no-op."""
138 182
139 183 if self._initialized:
140 184 return
141 185
142 186 # The first part is protected with an 'attempt' wrapper, that will log
143 187 # failures with the basic system traceback machinery. Once our crash
144 188 # handler is in place, we can let any subsequent exception propagate,
145 189 # as our handler will log it with much better detail than the default.
146 190 self.attempt(self.create_crash_handler)
191
192 # Configuration phase
193 # Default config (internally hardwired in application code)
147 194 self.create_default_config()
148 195 self.log_default_config()
149 196 self.set_default_config_log_level()
150 self.pre_load_command_line_config()
151 self.load_command_line_config()
152 self.set_command_line_config_log_level()
153 self.post_load_command_line_config()
154 self.log_command_line_config()
197
198 if self.override_config is None:
199 # Command-line config
200 self.pre_load_command_line_config()
201 self.load_command_line_config()
202 self.set_command_line_config_log_level()
203 self.post_load_command_line_config()
204 self.log_command_line_config()
205
206 # Find resources needed for filesystem access, using information from
207 # the above two
155 208 self.find_ipython_dir()
156 209 self.find_resources()
157 210 self.find_config_file_name()
158 211 self.find_config_file_paths()
159 self.pre_load_file_config()
160 self.load_file_config()
161 self.set_file_config_log_level()
162 self.post_load_file_config()
163 self.log_file_config()
212
213 if self.override_config is None:
214 # File-based config
215 self.pre_load_file_config()
216 self.load_file_config()
217 self.set_file_config_log_level()
218 self.post_load_file_config()
219 self.log_file_config()
220
221 # Merge all config objects into a single one the app can then use
164 222 self.merge_configs()
165 223 self.log_master_config()
224
225 # Construction phase
166 226 self.pre_construct()
167 227 self.construct()
168 228 self.post_construct()
229
230 # Done, flag as such and
169 231 self._initialized = True
170 232
171 233 def start(self):
234 """Start the application."""
172 235 self.initialize()
173 236 self.start_app()
174 237
175 238 #-------------------------------------------------------------------------
176 239 # Various stages of Application creation
177 240 #-------------------------------------------------------------------------
178 241
179 242 def create_crash_handler(self):
180 243 """Create a crash handler, typically setting sys.excepthook to it."""
181 244 self.crash_handler = self._CrashHandler(self, self.name)
182 245 sys.excepthook = self.crash_handler
183 246
184 247 def create_default_config(self):
185 248 """Create defaults that can't be set elsewhere.
186 249
187 250 For the most part, we try to set default in the class attributes
188 251 of Components. But, defaults the top-level Application (which is
189 252 not a HasTraitlets or Component) are not set in this way. Instead
190 253 we set them here. The Global section is for variables like this that
191 254 don't belong to a particular component.
192 255 """
193 256 c = Config()
194 257 c.Global.ipython_dir = get_ipython_dir()
195 258 c.Global.log_level = self.log_level
196 259 self.default_config = c
197 260
198 261 def log_default_config(self):
199 262 self.log.debug('Default config loaded:')
200 263 self.log.debug(repr(self.default_config))
201 264
202 265 def set_default_config_log_level(self):
203 266 try:
204 267 self.log_level = self.default_config.Global.log_level
205 268 except AttributeError:
206 269 # Fallback to the default_log_level class attribute
207 270 pass
208 271
209 272 def create_command_line_config(self):
210 273 """Create and return a command line config loader."""
211 274 return ArgParseConfigLoader(self.argv, self.cl_arguments,
212 275 description=self.description,
213 276 version=release.version,
214 277 usage=self.usage,
215 278 )
216 279
217 280 def pre_load_command_line_config(self):
218 281 """Do actions just before loading the command line config."""
219 282 pass
220 283
221 284 def load_command_line_config(self):
222 285 """Load the command line config."""
223 286 loader = self.create_command_line_config()
224 287 self.command_line_config = loader.load_config()
225 288 self.extra_args = loader.get_extra_args()
226 289
227 290 def set_command_line_config_log_level(self):
228 291 try:
229 292 self.log_level = self.command_line_config.Global.log_level
230 293 except AttributeError:
231 294 pass
232 295
233 296 def post_load_command_line_config(self):
234 297 """Do actions just after loading the command line config."""
235 298 pass
236 299
237 300 def log_command_line_config(self):
238 301 self.log.debug("Command line config loaded:")
239 302 self.log.debug(repr(self.command_line_config))
240 303
241 304 def find_ipython_dir(self):
242 305 """Set the IPython directory.
243 306
244 307 This sets ``self.ipython_dir``, but the actual value that is passed to
245 308 the application is kept in either ``self.default_config`` or
246 309 ``self.command_line_config``. This also adds ``self.ipython_dir`` to
247 310 ``sys.path`` so config files there can be referenced by other config
248 311 files.
249 312 """
250 313
251 314 try:
252 315 self.ipython_dir = self.command_line_config.Global.ipython_dir
253 316 except AttributeError:
254 317 self.ipython_dir = self.default_config.Global.ipython_dir
255 318 sys.path.append(os.path.abspath(self.ipython_dir))
256 319 if not os.path.isdir(self.ipython_dir):
257 320 os.makedirs(self.ipython_dir, mode=0777)
258 321 self.log.debug("IPYTHON_DIR set to: %s" % self.ipython_dir)
259 322
260 323 def find_resources(self):
261 324 """Find other resources that need to be in place.
262 325
263 326 Things like cluster directories need to be in place to find the
264 327 config file. These happen right after the IPython directory has
265 328 been set.
266 329 """
267 330 pass
268 331
269 332 def find_config_file_name(self):
270 333 """Find the config file name for this application.
271 334
272 335 This must set ``self.config_file_name`` to the filename of the
273 336 config file to use (just the filename). The search paths for the
274 337 config file are set in :meth:`find_config_file_paths` and then passed
275 338 to the config file loader where they are resolved to an absolute path.
276 339
277 340 If a profile has been set at the command line, this will resolve it.
278 341 """
279 342
280 343 try:
281 344 self.config_file_name = self.command_line_config.Global.config_file
282 345 except AttributeError:
283 346 pass
284 347
285 348 try:
286 349 self.profile_name = self.command_line_config.Global.profile
287 350 except AttributeError:
288 351 pass
289 352 else:
290 353 name_parts = self.config_file_name.split('.')
291 354 name_parts.insert(1, u'_' + self.profile_name + u'.')
292 355 self.config_file_name = ''.join(name_parts)
293 356
294 357 def find_config_file_paths(self):
295 358 """Set the search paths for resolving the config file.
296 359
297 360 This must set ``self.config_file_paths`` to a sequence of search
298 361 paths to pass to the config file loader.
299 362 """
300 363 # Include our own profiles directory last, so that users can still find
301 364 # our shipped copies of builtin profiles even if they don't have them
302 365 # in their local ipython directory.
303 366 prof_dir = os.path.join(get_ipython_package_dir(), 'config', 'profile')
304 367 self.config_file_paths = (os.getcwd(), self.ipython_dir, prof_dir)
305 368
306 369 def pre_load_file_config(self):
307 370 """Do actions before the config file is loaded."""
308 371 pass
309 372
310 373 def load_file_config(self):
311 374 """Load the config file.
312 375
313 376 This tries to load the config file from disk. If successful, the
314 377 ``CONFIG_FILE`` config variable is set to the resolved config file
315 378 location. If not successful, an empty config is used.
316 379 """
317 380 self.log.debug("Attempting to load config file: %s" %
318 381 self.config_file_name)
319 382 loader = PyFileConfigLoader(self.config_file_name,
320 383 path=self.config_file_paths)
321 384 try:
322 385 self.file_config = loader.load_config()
323 386 self.file_config.Global.config_file = loader.full_filename
324 387 except IOError:
325 388 # Only warn if the default config file was NOT being used.
326 389 if not self.config_file_name==self.default_config_file_name:
327 390 self.log.warn("Config file not found, skipping: %s" %
328 391 self.config_file_name, exc_info=True)
329 392 self.file_config = Config()
330 393 except:
331 394 self.log.warn("Error loading config file: %s" %
332 395 self.config_file_name, exc_info=True)
333 396 self.file_config = Config()
334 397
335 398 def set_file_config_log_level(self):
336 399 # We need to keeep self.log_level updated. But we only use the value
337 400 # of the file_config if a value was not specified at the command
338 401 # line, because the command line overrides everything.
339 402 if not hasattr(self.command_line_config.Global, 'log_level'):
340 403 try:
341 404 self.log_level = self.file_config.Global.log_level
342 405 except AttributeError:
343 406 pass # Use existing value
344 407
345 408 def post_load_file_config(self):
346 409 """Do actions after the config file is loaded."""
347 410 pass
348 411
349 412 def log_file_config(self):
350 413 if hasattr(self.file_config.Global, 'config_file'):
351 414 self.log.debug("Config file loaded: %s" %
352 415 self.file_config.Global.config_file)
353 416 self.log.debug(repr(self.file_config))
354 417
355 418 def merge_configs(self):
356 419 """Merge the default, command line and file config objects."""
357 420 config = Config()
358 421 config._merge(self.default_config)
359 config._merge(self.file_config)
360 config._merge(self.command_line_config)
422 if self.override_config is None:
423 config._merge(self.file_config)
424 config._merge(self.command_line_config)
425 if self.constructor_config is not None:
426 config._merge(self.constructor_config)
427 else:
428 config._merge(self.override_config)
429 # XXX fperez - propose to Brian we rename master_config to simply
430 # config, I think this is going to be heavily used in examples and
431 # application code and the name is shorter/easier to find/remember.
432 # For now, just alias it...
361 433 self.master_config = config
434 self.config = config
362 435
363 436 def log_master_config(self):
364 437 self.log.debug("Master config created:")
365 438 self.log.debug(repr(self.master_config))
366 439
367 440 def pre_construct(self):
368 441 """Do actions after the config has been built, but before construct."""
369 442 pass
370 443
371 444 def construct(self):
372 445 """Construct the main components that make up this app."""
373 446 self.log.debug("Constructing components for application")
374 447
375 448 def post_construct(self):
376 449 """Do actions after construct, but before starting the app."""
377 450 pass
378 451
379 452 def start_app(self):
380 453 """Actually start the app."""
381 454 self.log.debug("Starting application")
382 455
383 456 #-------------------------------------------------------------------------
384 457 # Utility methods
385 458 #-------------------------------------------------------------------------
386 459
387 460 def abort(self):
388 461 """Abort the starting of the application."""
389 462 if self._exiting:
390 463 pass
391 464 else:
392 465 self.log.critical("Aborting application: %s" % self.name, exc_info=True)
393 466 self._exiting = True
394 467 sys.exit(1)
395 468
396 469 def exit(self, exit_status=0):
397 470 if self._exiting:
398 471 pass
399 472 else:
400 473 self.log.debug("Exiting application: %s" % self.name)
401 474 self._exiting = True
402 475 sys.exit(exit_status)
403 476
404 477 def attempt(self, func, action='abort'):
405 478 try:
406 479 func()
407 480 except SystemExit:
408 481 raise
409 482 except:
410 483 if action == 'abort':
411 484 self.log.critical("Aborting application: %s" % self.name,
412 485 exc_info=True)
413 486 self.abort()
414 487 raise
415 488 elif action == 'exit':
416 489 self.exit(0)
417 490
@@ -1,643 +1,655 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 """
13 13
14 14 #-----------------------------------------------------------------------------
15 15 # Copyright (C) 2008-2010 The IPython Development Team
16 16 #
17 17 # Distributed under the terms of the BSD License. The full license is in
18 18 # the file COPYING, distributed as part of this software.
19 19 #-----------------------------------------------------------------------------
20 20
21 21 #-----------------------------------------------------------------------------
22 22 # Imports
23 23 #-----------------------------------------------------------------------------
24 24 from __future__ import absolute_import
25 25
26 26 import logging
27 27 import os
28 28 import sys
29 29
30 30 from IPython.core import crashhandler
31 31 from IPython.core.application import Application
32 32 from IPython.core.iplib import InteractiveShell
33 33 from IPython.config.loader import (
34 34 Config,
35 35 PyFileConfigLoader,
36 36 # NoConfigDefault,
37 37 )
38 38 from IPython.lib import inputhook
39 39 from IPython.utils.genutils import filefind, get_ipython_dir
40 40 from . import usage
41 41
42 42 #-----------------------------------------------------------------------------
43 43 # Globals, utilities and helpers
44 44 #-----------------------------------------------------------------------------
45 45
46 46 default_config_file_name = u'ipython_config.py'
47 47
48 48 cl_args = (
49 49 (('--autocall',), dict(
50 50 type=int, dest='InteractiveShell.autocall',
51 51 help=
52 52 """Make IPython automatically call any callable object even if you
53 53 didn't type explicit parentheses. For example, 'str 43' becomes
54 54 'str(43)' automatically. The value can be '0' to disable the feature,
55 55 '1' for 'smart' autocall, where it is not applied if there are no more
56 56 arguments on the line, and '2' for 'full' autocall, where all callable
57 57 objects are automatically called (even if no arguments are present).
58 58 The default is '1'.""",
59 59 metavar='InteractiveShell.autocall')
60 60 ),
61 61 (('--autoindent',), dict(
62 62 action='store_true', dest='InteractiveShell.autoindent',
63 63 help='Turn on autoindenting.')
64 64 ),
65 65 (('--no-autoindent',), dict(
66 66 action='store_false', dest='InteractiveShell.autoindent',
67 67 help='Turn off autoindenting.')
68 68 ),
69 69 (('--automagic',), dict(
70 70 action='store_true', dest='InteractiveShell.automagic',
71 71 help='Turn on the auto calling of magic commands.'
72 72 'Type %%magic at the IPython prompt for more information.')
73 73 ),
74 74 (('--no-automagic',), dict(
75 75 action='store_false', dest='InteractiveShell.automagic',
76 76 help='Turn off the auto calling of magic commands.')
77 77 ),
78 78 (('--autoedit-syntax',), dict(
79 79 action='store_true', dest='InteractiveShell.autoedit_syntax',
80 80 help='Turn on auto editing of files with syntax errors.')
81 81 ),
82 82 (('--no-autoedit-syntax',), dict(
83 83 action='store_false', dest='InteractiveShell.autoedit_syntax',
84 84 help='Turn off auto editing of files with syntax errors.')
85 85 ),
86 86 (('--banner',), dict(
87 87 action='store_true', dest='Global.display_banner',
88 88 help='Display a banner upon starting IPython.')
89 89 ),
90 90 (('--no-banner',), dict(
91 91 action='store_false', dest='Global.display_banner',
92 92 help="Don't display a banner upon starting IPython.")
93 93 ),
94 94 (('--cache-size',), dict(
95 95 type=int, dest='InteractiveShell.cache_size',
96 96 help=
97 97 """Set the size of the output cache. The default is 1000, you can
98 98 change it permanently in your config file. Setting it to 0 completely
99 99 disables the caching system, and the minimum value accepted is 20 (if
100 100 you provide a value less than 20, it is reset to 0 and a warning is
101 101 issued). This limit is defined because otherwise you'll spend more
102 102 time re-flushing a too small cache than working.
103 103 """,
104 104 metavar='InteractiveShell.cache_size')
105 105 ),
106 106 (('--classic',), dict(
107 107 action='store_true', dest='Global.classic',
108 108 help="Gives IPython a similar feel to the classic Python prompt.")
109 109 ),
110 110 (('--colors',), dict(
111 111 type=str, dest='InteractiveShell.colors',
112 112 help="Set the color scheme (NoColor, Linux, and LightBG).",
113 113 metavar='InteractiveShell.colors')
114 114 ),
115 115 (('--color-info',), dict(
116 116 action='store_true', dest='InteractiveShell.color_info',
117 117 help=
118 118 """IPython can display information about objects via a set of func-
119 119 tions, and optionally can use colors for this, syntax highlighting
120 120 source code and various other elements. However, because this
121 121 information is passed through a pager (like 'less') and many pagers get
122 122 confused with color codes, this option is off by default. You can test
123 123 it and turn it on permanently in your ipython_config.py file if it
124 124 works for you. Test it and turn it on permanently if it works with
125 125 your system. The magic function %%color_info allows you to toggle this
126 126 inter- actively for testing."""
127 127 )
128 128 ),
129 129 (('--no-color-info',), dict(
130 130 action='store_false', dest='InteractiveShell.color_info',
131 131 help="Disable using colors for info related things.")
132 132 ),
133 133 (('--confirm-exit',), dict(
134 134 action='store_true', dest='InteractiveShell.confirm_exit',
135 135 help=
136 136 """Set to confirm when you try to exit IPython with an EOF (Control-D
137 137 in Unix, Control-Z/Enter in Windows). By typing 'exit', 'quit' or
138 138 '%%Exit', you can force a direct exit without any confirmation.
139 139 """
140 140 )
141 141 ),
142 142 (('--no-confirm-exit',), dict(
143 143 action='store_false', dest='InteractiveShell.confirm_exit',
144 144 help="Don't prompt the user when exiting.")
145 145 ),
146 146 (('--deep-reload',), dict(
147 147 action='store_true', dest='InteractiveShell.deep_reload',
148 148 help=
149 149 """Enable deep (recursive) reloading by default. IPython can use the
150 150 deep_reload module which reloads changes in modules recursively (it
151 151 replaces the reload() function, so you don't need to change anything to
152 152 use it). deep_reload() forces a full reload of modules whose code may
153 153 have changed, which the default reload() function does not. When
154 154 deep_reload is off, IPython will use the normal reload(), but
155 155 deep_reload will still be available as dreload(). This fea- ture is off
156 156 by default [which means that you have both normal reload() and
157 157 dreload()].""")
158 158 ),
159 159 (('--no-deep-reload',), dict(
160 160 action='store_false', dest='InteractiveShell.deep_reload',
161 161 help="Disable deep (recursive) reloading by default.")
162 162 ),
163 163 (('--editor',), dict(
164 164 type=str, dest='InteractiveShell.editor',
165 165 help="Set the editor used by IPython (default to $EDITOR/vi/notepad).",
166 166 metavar='InteractiveShell.editor')
167 167 ),
168 168 (('--log','-l'), dict(
169 169 action='store_true', dest='InteractiveShell.logstart',
170 170 help="Start logging to the default log file (./ipython_log.py).")
171 171 ),
172 172 (('--logfile','-lf'), dict(
173 173 type=unicode, dest='InteractiveShell.logfile',
174 174 help="Start logging to logfile with this name.",
175 175 metavar='InteractiveShell.logfile')
176 176 ),
177 177 (('--log-append','-la'), dict(
178 178 type=unicode, dest='InteractiveShell.logappend',
179 179 help="Start logging to the given file in append mode.",
180 180 metavar='InteractiveShell.logfile')
181 181 ),
182 182 (('--pdb',), dict(
183 183 action='store_true', dest='InteractiveShell.pdb',
184 184 help="Enable auto calling the pdb debugger after every exception.")
185 185 ),
186 186 (('--no-pdb',), dict(
187 187 action='store_false', dest='InteractiveShell.pdb',
188 188 help="Disable auto calling the pdb debugger after every exception.")
189 189 ),
190 190 (('--pprint',), dict(
191 191 action='store_true', dest='InteractiveShell.pprint',
192 192 help="Enable auto pretty printing of results.")
193 193 ),
194 194 (('--no-pprint',), dict(
195 195 action='store_false', dest='InteractiveShell.pprint',
196 196 help="Disable auto auto pretty printing of results.")
197 197 ),
198 198 (('--prompt-in1','-pi1'), dict(
199 199 type=str, dest='InteractiveShell.prompt_in1',
200 200 help=
201 201 """Set the main input prompt ('In [\#]: '). Note that if you are using
202 202 numbered prompts, the number is represented with a '\#' in the string.
203 203 Don't forget to quote strings with spaces embedded in them. Most
204 204 bash-like escapes can be used to customize IPython's prompts, as well
205 205 as a few additional ones which are IPython-spe- cific. All valid
206 206 prompt escapes are described in detail in the Customization section of
207 207 the IPython manual.""",
208 208 metavar='InteractiveShell.prompt_in1')
209 209 ),
210 210 (('--prompt-in2','-pi2'), dict(
211 211 type=str, dest='InteractiveShell.prompt_in2',
212 212 help=
213 213 """Set the secondary input prompt (' .\D.: '). Similar to the previous
214 214 option, but used for the continuation prompts. The special sequence
215 215 '\D' is similar to '\#', but with all digits replaced by dots (so you
216 216 can have your continuation prompt aligned with your input prompt).
217 217 Default: ' .\D.: ' (note three spaces at the start for alignment with
218 218 'In [\#]')""",
219 219 metavar='InteractiveShell.prompt_in2')
220 220 ),
221 221 (('--prompt-out','-po'), dict(
222 222 type=str, dest='InteractiveShell.prompt_out',
223 223 help="Set the output prompt ('Out[\#]:')",
224 224 metavar='InteractiveShell.prompt_out')
225 225 ),
226 226 (('--quick',), dict(
227 227 action='store_true', dest='Global.quick',
228 228 help="Enable quick startup with no config files.")
229 229 ),
230 230 (('--readline',), dict(
231 231 action='store_true', dest='InteractiveShell.readline_use',
232 232 help="Enable readline for command line usage.")
233 233 ),
234 234 (('--no-readline',), dict(
235 235 action='store_false', dest='InteractiveShell.readline_use',
236 236 help="Disable readline for command line usage.")
237 237 ),
238 238 (('--screen-length','-sl'), dict(
239 239 type=int, dest='InteractiveShell.screen_length',
240 240 help=
241 241 """Number of lines of your screen, used to control printing of very
242 242 long strings. Strings longer than this number of lines will be sent
243 243 through a pager instead of directly printed. The default value for
244 244 this is 0, which means IPython will auto-detect your screen size every
245 245 time it needs to print certain potentially long strings (this doesn't
246 246 change the behavior of the 'print' keyword, it's only triggered
247 247 internally). If for some reason this isn't working well (it needs
248 248 curses support), specify it yourself. Otherwise don't change the
249 249 default.""",
250 250 metavar='InteractiveShell.screen_length')
251 251 ),
252 252 (('--separate-in','-si'), dict(
253 253 type=str, dest='InteractiveShell.separate_in',
254 254 help="Separator before input prompts. Default '\\n'.",
255 255 metavar='InteractiveShell.separate_in')
256 256 ),
257 257 (('--separate-out','-so'), dict(
258 258 type=str, dest='InteractiveShell.separate_out',
259 259 help="Separator before output prompts. Default 0 (nothing).",
260 260 metavar='InteractiveShell.separate_out')
261 261 ),
262 262 (('--separate-out2','-so2'), dict(
263 263 type=str, dest='InteractiveShell.separate_out2',
264 264 help="Separator after output prompts. Default 0 (nonight).",
265 265 metavar='InteractiveShell.separate_out2')
266 266 ),
267 267 (('-no-sep',), dict(
268 268 action='store_true', dest='Global.nosep',
269 269 help="Eliminate all spacing between prompts.")
270 270 ),
271 271 (('--term-title',), dict(
272 272 action='store_true', dest='InteractiveShell.term_title',
273 273 help="Enable auto setting the terminal title.")
274 274 ),
275 275 (('--no-term-title',), dict(
276 276 action='store_false', dest='InteractiveShell.term_title',
277 277 help="Disable auto setting the terminal title.")
278 278 ),
279 279 (('--xmode',), dict(
280 280 type=str, dest='InteractiveShell.xmode',
281 281 help=
282 282 """Exception reporting mode ('Plain','Context','Verbose'). Plain:
283 283 similar to python's normal traceback printing. Context: prints 5 lines
284 284 of context source code around each line in the traceback. Verbose:
285 285 similar to Context, but additionally prints the variables currently
286 286 visible where the exception happened (shortening their strings if too
287 287 long). This can potentially be very slow, if you happen to have a huge
288 288 data structure whose string representation is complex to compute.
289 289 Your computer may appear to freeze for a while with cpu usage at 100%%.
290 290 If this occurs, you can cancel the traceback with Ctrl-C (maybe hitting
291 291 it more than once).
292 292 """,
293 293 metavar='InteractiveShell.xmode')
294 294 ),
295 295 (('--ext',), dict(
296 296 type=str, dest='Global.extra_extension',
297 297 help="The dotted module name of an IPython extension to load.",
298 298 metavar='Global.extra_extension')
299 299 ),
300 300 (('-c',), dict(
301 301 type=str, dest='Global.code_to_run',
302 302 help="Execute the given command string.",
303 303 metavar='Global.code_to_run')
304 304 ),
305 305 (('-i',), dict(
306 306 action='store_true', dest='Global.force_interact',
307 307 help=
308 308 "If running code from the command line, become interactive afterwards."
309 309 )
310 310 ),
311 311
312 312 # Options to start with GUI control enabled from the beginning
313 313 (('--gui',), dict(
314 314 type=str, dest='Global.gui',
315 315 help="Enable GUI event loop integration ('qt', 'wx', 'gtk').",
316 316 metavar='gui-mode')
317 317 ),
318 318
319 319 (('--pylab','-pylab'), dict(
320 320 type=str, dest='Global.pylab',
321 321 nargs='?', const='auto', metavar='gui-mode',
322 322 help="Pre-load matplotlib and numpy for interactive use. "+
323 323 "If no value is given, the gui backend is matplotlib's, else use "+
324 324 "one of: ['tk', 'qt', 'wx', 'gtk'].")
325 325 ),
326 326
327 327 # Legacy GUI options. Leave them in for backwards compatibility, but the
328 328 # 'thread' names are really a misnomer now.
329 329 (('--wthread','-wthread'), dict(
330 330 action='store_true', dest='Global.wthread',
331 331 help="Enable wxPython event loop integration "+
332 332 "(DEPRECATED, use --gui wx)")
333 333 ),
334 334 (('--q4thread','--qthread','-q4thread','-qthread'), dict(
335 335 action='store_true', dest='Global.q4thread',
336 336 help="Enable Qt4 event loop integration. Qt3 is no longer supported. "+
337 337 "(DEPRECATED, use --gui qt)")
338 338 ),
339 339 (('--gthread','-gthread'), dict(
340 340 action='store_true', dest='Global.gthread',
341 341 help="Enable GTK event loop integration. "+
342 342 "(DEPRECATED, use --gui gtk)")
343 343 ),
344 344 )
345 345
346 346 #-----------------------------------------------------------------------------
347 347 # Main classes and functions
348 348 #-----------------------------------------------------------------------------
349 349
350 350 class IPythonApp(Application):
351 351 name = u'ipython'
352 352 #: argparse formats better the 'usage' than the 'description' field
353 353 description = None
354 354 #: usage message printed by argparse. If None, auto-generate
355 355 usage = usage.cl_usage
356 356
357 357 config_file_name = default_config_file_name
358 358
359 359 cl_arguments = Application.cl_arguments + cl_args
360 360
361 361 # Private and configuration attributes
362 362 _CrashHandler = crashhandler.IPythonCrashHandler
363 363
364 def __init__(self, argv=None, **shell_params):
364 def __init__(self, argv=None,
365 constructor_config=None, override_config=None,
366 **shell_params):
365 367 """Create a new IPythonApp.
366 368
369 See the parent class for details on how configuration is handled.
370
367 371 Parameters
368 372 ----------
369 373 argv : optional, list
370 374 If given, used as the command-line argv environment to read arguments
371 375 from.
372 376
377 constructor_config : optional, Config
378 If given, additional config that is merged last, after internal
379 defaults, command-line and file-based configs.
380
381 override_config : optional, Config
382 If given, config that overrides all others unconditionally (except
383 for internal defaults, which ensure that all parameters exist).
384
373 385 shell_params : optional, dict
374 386 All other keywords are passed to the :class:`iplib.InteractiveShell`
375 387 constructor.
376 388 """
377 super(IPythonApp, self).__init__(argv)
389 super(IPythonApp, self).__init__(argv, constructor_config,
390 override_config)
378 391 self.shell_params = shell_params
379 392
380 393 def create_default_config(self):
381 394 super(IPythonApp, self).create_default_config()
382 395 # Eliminate multiple lookups
383 396 Global = self.default_config.Global
384 397
385 398 # Set all default values
386 399 Global.display_banner = True
387 400
388 401 # If the -c flag is given or a file is given to run at the cmd line
389 402 # like "ipython foo.py", normally we exit without starting the main
390 403 # loop. The force_interact config variable allows a user to override
391 404 # this and interact. It is also set by the -i cmd line flag, just
392 405 # like Python.
393 406 Global.force_interact = False
394 407
395 408 # By default always interact by starting the IPython mainloop.
396 409 Global.interact = True
397 410
398 411 # No GUI integration by default
399 412 Global.gui = False
400 413 # Pylab off by default
401 414 Global.pylab = False
402 415
403 416 # Deprecated versions of gui support that used threading, we support
404 417 # them just for bacwards compatibility as an alternate spelling for
405 418 # '--gui X'
406 419 Global.qthread = False
407 420 Global.q4thread = False
408 421 Global.wthread = False
409 422 Global.gthread = False
410 423
411 424 def load_file_config(self):
412 425 if hasattr(self.command_line_config.Global, 'quick'):
413 426 if self.command_line_config.Global.quick:
414 427 self.file_config = Config()
415 428 return
416 429 super(IPythonApp, self).load_file_config()
417 430
418 431 def post_load_file_config(self):
419 432 if hasattr(self.command_line_config.Global, 'extra_extension'):
420 433 if not hasattr(self.file_config.Global, 'extensions'):
421 434 self.file_config.Global.extensions = []
422 435 self.file_config.Global.extensions.append(
423 436 self.command_line_config.Global.extra_extension)
424 437 del self.command_line_config.Global.extra_extension
425 438
426 439 def pre_construct(self):
427 440 config = self.master_config
428 441
429 442 if hasattr(config.Global, 'classic'):
430 443 if config.Global.classic:
431 444 config.InteractiveShell.cache_size = 0
432 445 config.InteractiveShell.pprint = 0
433 446 config.InteractiveShell.prompt_in1 = '>>> '
434 447 config.InteractiveShell.prompt_in2 = '... '
435 448 config.InteractiveShell.prompt_out = ''
436 449 config.InteractiveShell.separate_in = \
437 450 config.InteractiveShell.separate_out = \
438 451 config.InteractiveShell.separate_out2 = ''
439 452 config.InteractiveShell.colors = 'NoColor'
440 453 config.InteractiveShell.xmode = 'Plain'
441 454
442 455 if hasattr(config.Global, 'nosep'):
443 456 if config.Global.nosep:
444 457 config.InteractiveShell.separate_in = \
445 458 config.InteractiveShell.separate_out = \
446 459 config.InteractiveShell.separate_out2 = ''
447 460
448 461 # if there is code of files to run from the cmd line, don't interact
449 462 # unless the -i flag (Global.force_interact) is true.
450 463 code_to_run = config.Global.get('code_to_run','')
451 464 file_to_run = False
452 if len(self.extra_args)>=1:
453 if self.extra_args[0]:
465 if self.extra_args and self.extra_args[0]:
454 466 file_to_run = True
455 467 if file_to_run or code_to_run:
456 468 if not config.Global.force_interact:
457 469 config.Global.interact = False
458 470
459 471 def construct(self):
460 472 # I am a little hesitant to put these into InteractiveShell itself.
461 473 # But that might be the place for them
462 474 sys.path.insert(0, '')
463 475
464 476 # Create an InteractiveShell instance
465 477 self.shell = InteractiveShell(None, self.master_config,
466 478 **self.shell_params )
467 479
468 480 def post_construct(self):
469 481 """Do actions after construct, but before starting the app."""
470 482 config = self.master_config
471 483
472 484 # shell.display_banner should always be False for the terminal
473 485 # based app, because we call shell.show_banner() by hand below
474 486 # so the banner shows *before* all extension loading stuff.
475 487 self.shell.display_banner = False
476 488
477 489 if config.Global.display_banner and \
478 490 config.Global.interact:
479 491 self.shell.show_banner()
480 492
481 493 # Make sure there is a space below the banner.
482 494 if self.log_level <= logging.INFO: print
483 495
484 496 # Now a variety of things that happen after the banner is printed.
485 497 self._enable_gui_pylab()
486 498 self._load_extensions()
487 499 self._run_exec_lines()
488 500 self._run_exec_files()
489 501 self._run_cmd_line_code()
490 502 self._configure_xmode()
491 503
492 504 def _enable_gui_pylab(self):
493 505 """Enable GUI event loop integration, taking pylab into account."""
494 506 Global = self.master_config.Global
495 507
496 508 # Select which gui to use
497 509 if Global.gui:
498 510 gui = Global.gui
499 511 # The following are deprecated, but there's likely to be a lot of use
500 512 # of this form out there, so we might as well support it for now. But
501 513 # the --gui option above takes precedence.
502 514 elif Global.wthread:
503 515 gui = inputhook.GUI_WX
504 516 elif Global.qthread:
505 517 gui = inputhook.GUI_QT
506 518 elif Global.gthread:
507 519 gui = inputhook.GUI_GTK
508 520 else:
509 521 gui = None
510 522
511 523 # Using --pylab will also require gui activation, though which toolkit
512 524 # to use may be chosen automatically based on mpl configuration.
513 525 if Global.pylab:
514 526 activate = self.shell.enable_pylab
515 527 if Global.pylab == 'auto':
516 528 gui = None
517 529 else:
518 530 gui = Global.pylab
519 531 else:
520 532 # Enable only GUI integration, no pylab
521 533 activate = inputhook.enable_gui
522 534
523 535 if gui or Global.pylab:
524 536 try:
525 537 self.log.info("Enabling GUI event loop integration, "
526 538 "toolkit=%s, pylab=%s" % (gui, Global.pylab) )
527 539 activate(gui)
528 540 except:
529 541 self.log.warn("Error in enabling GUI event loop integration:")
530 542 self.shell.showtraceback()
531 543
532 544 def _load_extensions(self):
533 545 """Load all IPython extensions in Global.extensions.
534 546
535 547 This uses the :meth:`InteractiveShell.load_extensions` to load all
536 548 the extensions listed in ``self.master_config.Global.extensions``.
537 549 """
538 550 try:
539 551 if hasattr(self.master_config.Global, 'extensions'):
540 552 self.log.debug("Loading IPython extensions...")
541 553 extensions = self.master_config.Global.extensions
542 554 for ext in extensions:
543 555 try:
544 556 self.log.info("Loading IPython extension: %s" % ext)
545 557 self.shell.load_extension(ext)
546 558 except:
547 559 self.log.warn("Error in loading extension: %s" % ext)
548 560 self.shell.showtraceback()
549 561 except:
550 562 self.log.warn("Unknown error in loading extensions:")
551 563 self.shell.showtraceback()
552 564
553 565 def _run_exec_lines(self):
554 566 """Run lines of code in Global.exec_lines in the user's namespace."""
555 567 try:
556 568 if hasattr(self.master_config.Global, 'exec_lines'):
557 569 self.log.debug("Running code from Global.exec_lines...")
558 570 exec_lines = self.master_config.Global.exec_lines
559 571 for line in exec_lines:
560 572 try:
561 573 self.log.info("Running code in user namespace: %s" % line)
562 574 self.shell.runlines(line)
563 575 except:
564 576 self.log.warn("Error in executing line in user namespace: %s" % line)
565 577 self.shell.showtraceback()
566 578 except:
567 579 self.log.warn("Unknown error in handling Global.exec_lines:")
568 580 self.shell.showtraceback()
569 581
570 582 def _exec_file(self, fname):
571 583 full_filename = filefind(fname, [u'.', self.ipython_dir])
572 584 if os.path.isfile(full_filename):
573 585 if full_filename.endswith(u'.py'):
574 586 self.log.info("Running file in user namespace: %s" % full_filename)
575 587 self.shell.safe_execfile(full_filename, self.shell.user_ns)
576 588 elif full_filename.endswith('.ipy'):
577 589 self.log.info("Running file in user namespace: %s" % full_filename)
578 590 self.shell.safe_execfile_ipy(full_filename)
579 591 else:
580 592 self.log.warn("File does not have a .py or .ipy extension: <%s>" % full_filename)
581 593
582 594 def _run_exec_files(self):
583 595 try:
584 596 if hasattr(self.master_config.Global, 'exec_files'):
585 597 self.log.debug("Running files in Global.exec_files...")
586 598 exec_files = self.master_config.Global.exec_files
587 599 for fname in exec_files:
588 600 self._exec_file(fname)
589 601 except:
590 602 self.log.warn("Unknown error in handling Global.exec_files:")
591 603 self.shell.showtraceback()
592 604
593 605 def _run_cmd_line_code(self):
594 606 if hasattr(self.master_config.Global, 'code_to_run'):
595 607 line = self.master_config.Global.code_to_run
596 608 try:
597 609 self.log.info("Running code given at command line (-c): %s" % line)
598 610 self.shell.runlines(line)
599 611 except:
600 612 self.log.warn("Error in executing line in user namespace: %s" % line)
601 613 self.shell.showtraceback()
602 614 return
603 615 # Like Python itself, ignore the second if the first of these is present
604 616 try:
605 617 fname = self.extra_args[0]
606 618 except:
607 619 pass
608 620 else:
609 621 try:
610 622 self._exec_file(fname)
611 623 except:
612 624 self.log.warn("Error in executing file in user namespace: %s" % fname)
613 625 self.shell.showtraceback()
614 626
615 627 def _configure_xmode(self):
616 628 # XXX - shouldn't this be read from the config? I'm still a little
617 629 # lost with all the details of handling the new config guys...
618 630 self.shell.InteractiveTB.set_mode(mode=self.shell.xmode)
619 631
620 632 def start_app(self):
621 633 if self.master_config.Global.interact:
622 634 self.log.debug("Starting IPython's mainloop...")
623 635 self.shell.mainloop()
624 636 else:
625 637 self.log.debug("IPython not interactive, start_app is no-op...")
626 638
627 639
628 640 def load_default_config(ipython_dir=None):
629 641 """Load the default config file from the default ipython_dir.
630 642
631 643 This is useful for embedded shells.
632 644 """
633 645 if ipython_dir is None:
634 646 ipython_dir = get_ipython_dir()
635 647 cl = PyFileConfigLoader(default_config_file_name, ipython_dir)
636 648 config = cl.load_config()
637 649 return config
638 650
639 651
640 652 def launch_new_instance():
641 653 """Create and run a full blown IPython instance"""
642 654 app = IPythonApp()
643 655 app.start()
General Comments 0
You need to be logged in to leave comments. Login now