##// END OF EJS Templates
Merge pull request #4570 from chebee7i/ipydirective...
Thomas Kluyver -
r13909:95829b6e merge
parent child Browse files
Show More
@@ -0,0 +1,155 b''
1 """
2 Handlers for IPythonDirective's @doctest pseudo-decorator.
3
4 The Sphinx extension that provides support for embedded IPython code provides
5 a pseudo-decorator @doctest, which treats the input/output block as a
6 doctest, raising a RuntimeError during doc generation if the actual output
7 (after running the input) does not match the expected output.
8
9 An example usage is:
10
11 .. code-block:: rst
12
13 .. ipython::
14
15 In [1]: x = 1
16
17 @doctest
18 In [2]: x + 2
19 Out[3]: 3
20
21 One can also provide arguments to the decorator. The first argument should be
22 the name of a custom handler. The specification of any other arguments is
23 determined by the handler. For example,
24
25 .. code-block:: rst
26
27 .. ipython::
28
29 @doctest float
30 In [154]: 0.1 + 0.2
31 Out[154]: 0.3
32
33 allows the actual output ``0.30000000000000004`` to match the expected output
34 due to a comparison with `np.allclose`.
35
36 This module contains handlers for the @doctest pseudo-decorator. Handlers
37 should have the following function signature::
38
39 handler(sphinx_shell, args, input_lines, found, submitted)
40
41 where `sphinx_shell` is the embedded Sphinx shell, `args` contains the list
42 of arguments that follow: '@doctest handler_name', `input_lines` contains
43 a list of the lines relevant to the current doctest, `found` is a string
44 containing the output from the IPython shell, and `submitted` is a string
45 containing the expected output from the IPython shell.
46
47 Handlers must be registered in the `doctests` dict at the end of this module.
48
49 """
50
51 def str_to_array(s):
52 """
53 Simplistic converter of strings from repr to float NumPy arrays.
54
55 If the repr representation has ellipsis in it, then this will fail.
56
57 Parameters
58 ----------
59 s : str
60 The repr version of a NumPy array.
61
62 Examples
63 --------
64 >>> s = "array([ 0.3, inf, nan])"
65 >>> a = str_to_array(s)
66
67 """
68 import numpy as np
69
70 # Need to make sure eval() knows about inf and nan.
71 # This also assumes default printoptions for NumPy.
72 from numpy import inf, nan
73
74 if s.startswith(u'array'):
75 # Remove array( and )
76 s = s[6:-1]
77
78 if s.startswith(u'['):
79 a = np.array(eval(s), dtype=float)
80 else:
81 # Assume its a regular float. Force 1D so we can index into it.
82 a = np.atleast_1d(float(s))
83 return a
84
85 def float_doctest(sphinx_shell, args, input_lines, found, submitted):
86 """
87 Doctest which allow the submitted output to vary slightly from the input.
88
89 Here is how it might appear in an rst file:
90
91 .. code-block:: rst
92
93 .. ipython::
94
95 @doctest float
96 In [1]: 0.1 + 0.2
97 Out[1]: 0.3
98
99 """
100 import numpy as np
101
102 if len(args) == 2:
103 rtol = 1e-05
104 atol = 1e-08
105 else:
106 # Both must be specified if any are specified.
107 try:
108 rtol = float(args[2])
109 atol = float(args[3])
110 except IndexError:
111 e = ("Both `rtol` and `atol` must be specified "
112 "if either are specified: {0}".format(args))
113 raise IndexError(e)
114
115 try:
116 submitted = str_to_array(submitted)
117 found = str_to_array(found)
118 except:
119 # For example, if the array is huge and there are ellipsis in it.
120 error = True
121 else:
122 found_isnan = np.isnan(found)
123 submitted_isnan = np.isnan(submitted)
124 error = not np.allclose(found_isnan, submitted_isnan)
125 error |= not np.allclose(found[~found_isnan],
126 submitted[~submitted_isnan],
127 rtol=rtol, atol=atol)
128
129 TAB = ' ' * 4
130 directive = sphinx_shell.directive
131 if directive is None:
132 source = 'Unavailable'
133 content = 'Unavailable'
134 else:
135 source = directive.state.document.current_source
136 # Add tabs and make into a single string.
137 content = '\n'.join([TAB + line for line in directive.content])
138
139 if error:
140
141 e = ('doctest float comparison failure\n\n'
142 'Document source: {0}\n\n'
143 'Raw content: \n{1}\n\n'
144 'On input line(s):\n{TAB}{2}\n\n'
145 'we found output:\n{TAB}{3}\n\n'
146 'instead of the expected:\n{TAB}{4}\n\n')
147 e = e.format(source, content, '\n'.join(input_lines), repr(found),
148 repr(submitted), TAB=TAB)
149 raise RuntimeError(e)
150
151 # dict of allowable doctest handlers. The key represents the first argument
152 # that must be given to @doctest in order to activate the handler.
153 doctests = {
154 'float': float_doctest,
155 }
@@ -1,5 +1,6 b''
1 1 # -*- coding: utf-8 -*-
2 """Sphinx directive to support embedded IPython code.
2 """
3 Sphinx directive to support embedded IPython code.
3 4
4 5 This directive allows pasting of entire interactive IPython sessions, prompts
5 6 and all, and their code will actually get re-executed at doc build time, with
@@ -9,11 +10,17 b' like an interactive ipython section.'
9 10
10 11 To enable this directive, simply list it in your Sphinx ``conf.py`` file
11 12 (making sure the directory where you placed it is visible to sphinx, as is
12 needed for all Sphinx directives).
13 needed for all Sphinx directives). For example, to enable syntax highlighting
14 and the IPython directive::
15
16 extensions = ['IPython.sphinxext.ipython_console_highlighting',
17 'IPython.sphinxext.ipython_directive']
13 18
14 By default this directive assumes that your prompts are unchanged IPython ones,
15 but this can be customized. The configurable options that can be placed in
16 conf.py are
19 The IPython directive outputs code-blocks with the language 'ipython'. So
20 if you do not have the syntax highlighting extension enabled as well, then
21 all rendered code-blocks will be uncolored. By default this directive assumes
22 that your prompts are unchanged IPython ones, but this can be customized.
23 The configurable options that can be placed in conf.py are:
17 24
18 25 ipython_savefig_dir:
19 26 The directory in which to save the figures. This is relative to the
@@ -34,6 +41,47 b' ipython_promptout:'
34 41 The string to represent the IPython prompt in the generated ReST. The
35 42 default is 'Out [%d]:'. This expects that the line numbers are used
36 43 in the prompt.
44 ipython_mplbackend:
45 The string which specifies if the embedded Sphinx shell should import
46 Matplotlib and set the backend. The value specifies a backend that is
47 passed to `matplotlib.use()` before any lines in `ipython_execlines` are
48 executed. If not specified in conf.py, then the default value of 'agg' is
49 used. To use the IPython directive without matplotlib as a dependency, set
50 the value to `None`. It may end up that matplotlib is still imported
51 if the user specifies so in `ipython_execlines` or makes use of the
52 @savefig pseudo decorator.
53 ipython_execlines:
54 A list of strings to be exec'd in the embedded Sphinx shell. Typical
55 usage is to make certain packages always available. Set this to an empty
56 list if you wish to have no imports always available. If specified in
57 conf.py as `None`, then it has the effect of making no imports available.
58 If omitted from conf.py altogether, then the default value of
59 ['import numpy as np', 'import matplotlib.pyplot as plt'] is used.
60 ipython_holdcount
61 When the @suppress pseudo-decorator is used, the execution count can be
62 incremented or not. The default behavior is to hold the execution count,
63 corresponding to a value of `True`. Set this to `False` to increment
64 the execution count after each suppressed command.
65
66 As an example, to use the IPython directive when `matplotlib` is not available,
67 one sets the backend to `None`::
68
69 ipython_mplbackend = None
70
71 An example usage of the directive is:
72
73 .. code-block:: rst
74
75 .. ipython::
76
77 In [1]: x = 1
78
79 In [2]: y = x**2
80
81 In [3]: print(y)
82
83 See http://matplotlib.org/sampledoc/ipython_directive.html for additional
84 documentation.
37 85
38 86 ToDo
39 87 ----
@@ -70,14 +118,11 b' except ImportError:'
70 118 from md5 import md5
71 119
72 120 # Third-party
73 import matplotlib
74 121 import sphinx
75 122 from docutils.parsers.rst import directives
76 123 from docutils import nodes
77 124 from sphinx.util.compat import Directive
78 125
79 matplotlib.use('Agg')
80
81 126 # Our own
82 127 from IPython import Config, InteractiveShell
83 128 from IPython.core.profiledir import ProfileDir
@@ -98,6 +143,7 b' COMMENT, INPUT, OUTPUT = range(3)'
98 143 #-----------------------------------------------------------------------------
99 144 # Functions and class declarations
100 145 #-----------------------------------------------------------------------------
146
101 147 def block_parser(part, rgxin, rgxout, fmtin, fmtout):
102 148 """
103 149 part is a string of ipython text, comprised of at most one
@@ -116,10 +162,9 b' def block_parser(part, rgxin, rgxout, fmtin, fmtout):'
116 162 INPUT_LINE: the input as string (possibly multi-line)
117 163 REST : any stdout generated by the input line (not OUTPUT)
118 164
119
120 165 OUTPUT: the output string, possibly multi-line
121 """
122 166
167 """
123 168 block = []
124 169 lines = part.split('\n')
125 170 N = len(lines)
@@ -192,20 +237,19 b' def block_parser(part, rgxin, rgxout, fmtin, fmtout):'
192 237
193 238 return block
194 239
240
195 241 class EmbeddedSphinxShell(object):
196 242 """An embedded IPython instance to run inside Sphinx"""
197 243
198 def __init__(self):
244 def __init__(self, exec_lines=None):
199 245
200 246 self.cout = StringIO()
201 247
248 if exec_lines is None:
249 exec_lines = []
202 250
203 251 # Create config object for IPython
204 252 config = Config()
205 config.Global.display_banner = False
206 config.Global.exec_lines = ['import numpy as np',
207 'from pylab import *'
208 ]
209 253 config.InteractiveShell.autocall = False
210 254 config.InteractiveShell.autoindent = False
211 255 config.InteractiveShell.colors = 'NoColor'
@@ -216,9 +260,11 b' class EmbeddedSphinxShell(object):'
216 260 pdir = os.path.join(tmp_profile_dir,profname)
217 261 profile = ProfileDir.create_profile_dir(pdir)
218 262
219 # Create and initialize ipython, but don't start its mainloop
263 # Create and initialize global ipython, but don't start its mainloop.
264 # This will persist across different EmbededSphinxShell instances.
220 265 IP = InteractiveShell.instance(config=config, profile_dir=profile)
221 # io.stdout redirect must be done *after* instantiating InteractiveShell
266
267 # io.stdout redirect must be done after instantiating InteractiveShell
222 268 io.stdout = self.cout
223 269 io.stderr = self.cout
224 270
@@ -239,17 +285,24 b' class EmbeddedSphinxShell(object):'
239 285 self.is_doctest = False
240 286 self.is_suppress = False
241 287
288 # Optionally, provide more detailed information to shell.
289 self.directive = None
290
242 291 # on the first call to the savefig decorator, we'll import
243 292 # pyplot as plt so we can make a call to the plt.gcf().savefig
244 293 self._pyplot_imported = False
245 294
295 # Prepopulate the namespace.
296 for line in exec_lines:
297 self.process_input_line(line, store_history=False)
298
246 299 def clear_cout(self):
247 300 self.cout.seek(0)
248 301 self.cout.truncate(0)
249 302
250 303 def process_input_line(self, line, store_history=True):
251 304 """process the input, capturing stdout"""
252 #print "input='%s'"%self.input
305
253 306 stdout = sys.stdout
254 307 splitter = self.IP.input_splitter
255 308 try:
@@ -291,16 +344,19 b' class EmbeddedSphinxShell(object):'
291 344 image_directive = '\n'.join(imagerows)
292 345 return image_file, image_directive
293 346
294
295 347 # Callbacks for each type of token
296 348 def process_input(self, data, input_prompt, lineno):
297 """Process data block for INPUT token."""
349 """
350 Process data block for INPUT token.
351
352 """
298 353 decorator, input, rest = data
299 354 image_file = None
300 355 image_directive = None
301 #print 'INPUT:', data # dbg
356
302 357 is_verbatim = decorator=='@verbatim' or self.is_verbatim
303 is_doctest = decorator=='@doctest' or self.is_doctest
358 is_doctest = (decorator is not None and \
359 decorator.startswith('@doctest')) or self.is_doctest
304 360 is_suppress = decorator=='@suppress' or self.is_suppress
305 361 is_savefig = decorator is not None and \
306 362 decorator.startswith('@savefig')
@@ -312,7 +368,6 b' class EmbeddedSphinxShell(object):'
312 368 # so splitter buffer gets reset
313 369
314 370 continuation = ' %s:'%''.join(['.']*(len(str(lineno))+2))
315 Nc = len(continuation)
316 371
317 372 if is_savefig:
318 373 image_file, image_directive = self.process_image(decorator)
@@ -320,6 +375,12 b' class EmbeddedSphinxShell(object):'
320 375 ret = []
321 376 is_semicolon = False
322 377
378 # Hold the execution count, if requested to do so.
379 if is_suppress and self.hold_count:
380 store_history = False
381 else:
382 store_history = True
383
323 384 for i, line in enumerate(input_lines):
324 385 if line.endswith(';'):
325 386 is_semicolon = True
@@ -331,12 +392,12 b' class EmbeddedSphinxShell(object):'
331 392 self.IP.execution_count += 1 # increment it anyway
332 393 else:
333 394 # only submit the line in non-verbatim mode
334 self.process_input_line(line, store_history=True)
395 self.process_input_line(line, store_history=store_history)
335 396 formatted_line = '%s %s'%(input_prompt, line)
336 397 else:
337 398 # process a continuation line
338 399 if not is_verbatim:
339 self.process_input_line(line, store_history=True)
400 self.process_input_line(line, store_history=store_history)
340 401
341 402 formatted_line = '%s %s'%(continuation, line)
342 403
@@ -357,38 +418,61 b' class EmbeddedSphinxShell(object):'
357 418 ret.append('')
358 419
359 420 self.cout.truncate(0)
360 return (ret, input_lines, output, is_doctest, image_file,
421 return (ret, input_lines, output, is_doctest, decorator, image_file,
361 422 image_directive)
362 #print 'OUTPUT', output # dbg
423
363 424
364 425 def process_output(self, data, output_prompt,
365 input_lines, output, is_doctest, image_file):
366 """Process data block for OUTPUT token."""
367 if is_doctest:
368 submitted = data.strip()
426 input_lines, output, is_doctest, decorator, image_file):
427 """
428 Process data block for OUTPUT token.
429
430 """
431 TAB = ' ' * 4
432
433 if is_doctest and output is not None:
434
369 435 found = output
370 if found is not None:
371 436 found = found.strip()
437 submitted = data.strip()
372 438
373 # XXX - fperez: in 0.11, 'output' never comes with the prompt
374 # in it, just the actual output text. So I think all this code
375 # can be nuked...
376
377 # the above comment does not appear to be accurate... (minrk)
439 if self.directive is None:
440 source = 'Unavailable'
441 content = 'Unavailable'
442 else:
443 source = self.directive.state.document.current_source
444 content = self.directive.content
445 # Add tabs and join into a single string.
446 content = '\n'.join([TAB + line for line in content])
378 447
448 # Make sure the output contains the output prompt.
379 449 ind = found.find(output_prompt)
380 450 if ind<0:
381 e='output prompt="%s" does not match out line=%s' % \
382 (output_prompt, found)
451 e = ('output does not contain output prompt\n\n'
452 'Document source: {0}\n\n'
453 'Raw content: \n{1}\n\n'
454 'Input line(s):\n{TAB}{2}\n\n'
455 'Output line(s):\n{TAB}{3}\n\n')
456 e = e.format(source, content, '\n'.join(input_lines),
457 repr(found), TAB=TAB)
383 458 raise RuntimeError(e)
384 459 found = found[len(output_prompt):].strip()
385 460
461 # Handle the actual doctest comparison.
462 if decorator.strip() == '@doctest':
463 # Standard doctest
386 464 if found!=submitted:
387 e = ('doctest failure for input_lines="%s" with '
388 'found_output="%s" and submitted output="%s"' %
389 (input_lines, found, submitted) )
465 e = ('doctest failure\n\n'
466 'Document source: {0}\n\n'
467 'Raw content: \n{1}\n\n'
468 'On input line(s):\n{TAB}{2}\n\n'
469 'we found output:\n{TAB}{3}\n\n'
470 'instead of the expected:\n{TAB}{4}\n\n')
471 e = e.format(source, content, '\n'.join(input_lines),
472 repr(found), repr(submitted), TAB=TAB)
390 473 raise RuntimeError(e)
391 #print 'doctest PASSED for input_lines="%s" with found_output="%s" and submitted output="%s"'%(input_lines, found, submitted)
474 else:
475 self.custom_doctest(decorator, input_lines, found, submitted)
392 476
393 477 def process_comment(self, data):
394 478 """Process data fPblock for COMMENT token."""
@@ -409,7 +493,6 b' class EmbeddedSphinxShell(object):'
409 493 self.process_input_line('bookmark -d ipy_thisdir', store_history=False)
410 494 self.clear_cout()
411 495
412
413 496 def process_block(self, block):
414 497 """
415 498 process block from the block_parser and return a list of processed lines
@@ -428,14 +511,14 b' class EmbeddedSphinxShell(object):'
428 511 if token==COMMENT:
429 512 out_data = self.process_comment(data)
430 513 elif token==INPUT:
431 (out_data, input_lines, output, is_doctest, image_file,
432 image_directive) = \
514 (out_data, input_lines, output, is_doctest, decorator,
515 image_file, image_directive) = \
433 516 self.process_input(data, input_prompt, lineno)
434 517 elif token==OUTPUT:
435 518 out_data = \
436 519 self.process_output(data, output_prompt,
437 520 input_lines, output, is_doctest,
438 image_file)
521 decorator, image_file)
439 522 if out_data:
440 523 ret.extend(out_data)
441 524
@@ -446,14 +529,34 b' class EmbeddedSphinxShell(object):'
446 529 return ret, image_directive
447 530
448 531 def ensure_pyplot(self):
449 if self._pyplot_imported:
450 return
532 """
533 Ensures that pyplot has been imported into the embedded IPython shell.
534
535 Also, makes sure to set the backend appropriately if not set already.
536
537 """
538 # We are here if the @figure pseudo decorator was used. Thus, it's
539 # possible that we could be here even if python_mplbackend were set to
540 # `None`. That's also strange and perhaps worthy of raising an
541 # exception, but for now, we just set the backend to 'agg'.
542
543 if not self._pyplot_imported:
544 if 'matplotlib.backends' not in sys.modules:
545 # Then ipython_matplotlib was set to None but there was a
546 # call to the @figure decorator (and ipython_execlines did
547 # not set a backend).
548 #raise Exception("No backend was set, but @figure was used!")
549 import matplotlib
550 matplotlib.use('agg')
551
552 # Always import pyplot into embedded shell.
451 553 self.process_input_line('import matplotlib.pyplot as plt',
452 554 store_history=False)
555 self._pyplot_imported = True
453 556
454 557 def process_pure_python(self, content):
455 558 """
456 content is a list of strings. it is unedited directive conent
559 content is a list of strings. it is unedited directive content
457 560
458 561 This runs it line by line in the InteractiveShell, prepends
459 562 prompts as needed capturing stderr and stdout, then returns
@@ -529,6 +632,22 b' class EmbeddedSphinxShell(object):'
529 632
530 633 return output
531 634
635 def custom_doctest(self, decorator, input_lines, found, submitted):
636 """
637 Perform a specialized doctest.
638
639 """
640 from .custom_doctests import doctests
641
642 args = decorator.split()
643 doctest_type = args[1]
644 if doctest_type in doctests:
645 doctests[doctest_type](self, args, input_lines, found, submitted)
646 else:
647 e = "Invalid option to @doctest: {0}".format(doctest_type)
648 raise Exception(e)
649
650
532 651 class IPythonDirective(Directive):
533 652
534 653 has_content = True
@@ -564,27 +683,45 b' class IPythonDirective(Directive):'
564 683 rgxout = config.ipython_rgxout
565 684 promptin = config.ipython_promptin
566 685 promptout = config.ipython_promptout
686 mplbackend = config.ipython_mplbackend
687 exec_lines = config.ipython_execlines
688 hold_count = config.ipython_holdcount
567 689
568 return savefig_dir, source_dir, rgxin, rgxout, promptin, promptout
690 return (savefig_dir, source_dir, rgxin, rgxout,
691 promptin, promptout, mplbackend, exec_lines, hold_count)
569 692
570 693 def setup(self):
694 # Get configuration values.
695 (savefig_dir, source_dir, rgxin, rgxout, promptin, promptout,
696 mplbackend, exec_lines, hold_count) = self.get_config_options()
697
571 698 if self.shell is None:
572 self.shell = EmbeddedSphinxShell()
699 # We will be here many times. However, when the
700 # EmbeddedSphinxShell is created, its interactive shell member
701 # is the same for each instance.
702
703 if mplbackend:
704 import matplotlib
705 # Repeated calls to use() will not hurt us since `mplbackend`
706 # is the same each time.
707 matplotlib.use(mplbackend)
708
709 # Must be called after (potentially) importing matplotlib and
710 # setting its backend since exec_lines might import pylab.
711 self.shell = EmbeddedSphinxShell(exec_lines)
712
713 # Store IPython directive to enable better error messages
714 self.shell.directive = self
715
573 716 # reset the execution count if we haven't processed this doc
574 717 #NOTE: this may be borked if there are multiple seen_doc tmp files
575 718 #check time stamp?
576
577 719 if not self.state.document.current_source in self.seen_docs:
578 720 self.shell.IP.history_manager.reset()
579 721 self.shell.IP.execution_count = 1
722 self.shell.IP.prompt_manager.width = 0
580 723 self.seen_docs.add(self.state.document.current_source)
581 724
582
583
584 # get config values
585 (savefig_dir, source_dir, rgxin,
586 rgxout, promptin, promptout) = self.get_config_options()
587
588 725 # and attach to shell so we don't have to pass them around
589 726 self.shell.rgxin = rgxin
590 727 self.shell.rgxout = rgxout
@@ -592,16 +729,15 b' class IPythonDirective(Directive):'
592 729 self.shell.promptout = promptout
593 730 self.shell.savefig_dir = savefig_dir
594 731 self.shell.source_dir = source_dir
732 self.shell.hold_count = hold_count
595 733
596 734 # setup bookmark for saving figures directory
597
598 735 self.shell.process_input_line('bookmark ipy_savedir %s'%savefig_dir,
599 736 store_history=False)
600 737 self.shell.clear_cout()
601 738
602 739 return rgxin, rgxout, promptin, promptout
603 740
604
605 741 def teardown(self):
606 742 # delete last bookmark
607 743 self.shell.process_input_line('bookmark -d ipy_savedir',
@@ -620,7 +756,6 b' class IPythonDirective(Directive):'
620 756 self.shell.is_doctest = 'doctest' in options
621 757 self.shell.is_verbatim = 'verbatim' in options
622 758
623
624 759 # handle pure python code
625 760 if 'python' in self.arguments:
626 761 content = self.content
@@ -632,9 +767,7 b' class IPythonDirective(Directive):'
632 767 figures = []
633 768
634 769 for part in parts:
635
636 770 block = block_parser(part, rgxin, rgxout, promptin, promptout)
637
638 771 if len(block):
639 772 rows, figure = self.shell.process_block(block)
640 773 for row in rows:
@@ -643,46 +776,51 b' class IPythonDirective(Directive):'
643 776 if figure is not None:
644 777 figures.append(figure)
645 778
646 #text = '\n'.join(lines)
647 #figs = '\n'.join(figures)
648
649 779 for figure in figures:
650 780 lines.append('')
651 781 lines.extend(figure.split('\n'))
652 782 lines.append('')
653 783
654 #print lines
655 784 if len(lines)>2:
656 785 if debug:
657 786 print('\n'.join(lines))
658 else: #NOTE: this raises some errors, what's it for?
659 #print 'INSERTING %d lines'%len(lines)
787 else:
788 # This has to do with input, not output. But if we comment
789 # these lines out, then no IPython code will appear in the
790 # final output.
660 791 self.state_machine.insert_input(
661 792 lines, self.state_machine.input_lines.source(0))
662 793
663 text = '\n'.join(lines)
664 txtnode = nodes.literal_block(text, text)
665 txtnode['language'] = 'ipython'
666 #imgnode = nodes.image(figs)
667
668 794 # cleanup
669 795 self.teardown()
670 796
671 return []#, imgnode]
797 return []
672 798
673 799 # Enable as a proper Sphinx directive
674 800 def setup(app):
675 801 setup.app = app
676 802
677 803 app.add_directive('ipython', IPythonDirective)
678 app.add_config_value('ipython_savefig_dir', None, True)
804 app.add_config_value('ipython_savefig_dir', None, 'env')
679 805 app.add_config_value('ipython_rgxin',
680 re.compile('In \[(\d+)\]:\s?(.*)\s*'), True)
806 re.compile('In \[(\d+)\]:\s?(.*)\s*'), 'env')
681 807 app.add_config_value('ipython_rgxout',
682 re.compile('Out\[(\d+)\]:\s?(.*)\s*'), True)
683 app.add_config_value('ipython_promptin', 'In [%d]:', True)
684 app.add_config_value('ipython_promptout', 'Out[%d]:', True)
808 re.compile('Out\[(\d+)\]:\s?(.*)\s*'), 'env')
809 app.add_config_value('ipython_promptin', 'In [%d]:', 'env')
810 app.add_config_value('ipython_promptout', 'Out[%d]:', 'env')
811
812 # We could just let matplotlib pick whatever is specified as the default
813 # backend in the matplotlibrc file, but this would cause issues if the
814 # backend didn't work in headless environments. For this reason, 'agg'
815 # is a good default backend choice.
816 app.add_config_value('ipython_mplbackend', 'agg', 'env')
817
818 # If the user sets this config value to `None`, then EmbeddedSphinxShell's
819 # __init__ method will treat it as [].
820 execlines = ['import numpy as np', 'import matplotlib.pyplot as plt']
821 app.add_config_value('ipython_execlines', execlines, 'env')
685 822
823 app.add_config_value('ipython_holdcount', True, 'env')
686 824
687 825 # Simple smoke test, needs to be converted to a proper automatic test.
688 826 def test():
@@ -810,6 +948,33 b" In [152]: title('normal distribution')"
810 948 @savefig hist_with_text.png
811 949 In [153]: grid(True)
812 950
951 @doctest float
952 In [154]: 0.1 + 0.2
953 Out[154]: 0.3
954
955 @doctest float
956 In [155]: np.arange(16).reshape(4,4)
957 Out[155]:
958 array([[ 0, 1, 2, 3],
959 [ 4, 5, 6, 7],
960 [ 8, 9, 10, 11],
961 [12, 13, 14, 15]])
962
963 In [1]: x = np.arange(16, dtype=float).reshape(4,4)
964
965 In [2]: x[0,0] = np.inf
966
967 In [3]: x[0,1] = np.nan
968
969 @doctest float
970 In [4]: x
971 Out[4]:
972 array([[ inf, nan, 2., 3.],
973 [ 4., 5., 6., 7.],
974 [ 8., 9., 10., 11.],
975 [ 12., 13., 14., 15.]])
976
977
813 978 """,
814 979 ]
815 980 # skip local-file depending first example:
General Comments 0
You need to be logged in to leave comments. Login now