##// END OF EJS Templates
Updated Sphinx extension ipython_directive to work with 0.11.
Skipper Seabold -
Show More
@@ -3,38 +3,38 b''
3 3
4 4 This directive allows pasting of entire interactive IPython sessions, prompts
5 5 and all, and their code will actually get re-executed at doc build time, with
6 all prompts renumbered sequentially.
6 all prompts renumbered sequentially. It also allows you to input code as a pure
7 python input by giving the argument python to the directive. The output looks
8 like an interactive ipython section.
7 9
8 10 To enable this directive, simply list it in your Sphinx ``conf.py`` file
9 11 (making sure the directory where you placed it is visible to sphinx, as is
10 12 needed for all Sphinx directives).
11 13
12 14 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
15 but this can be customized. The configurable options that can be placed in
16 conf.py are
17
18 ipython_savefig_dir:
19 The directory in which to save the figures. This is relative to the
20 Sphinx source directory. The default is `html_static_path`.
21 ipython_rgxin:
22 The compiled regular expression to denote the start of IPython input
23 lines. The default is re.compile('In \[(\d+)\]:\s?(.*)\s*'). You
24 shouldn't need to change this.
25 ipython_rgxout:
26 The compiled regular expression to denote the start of IPython output
27 lines. The default is re.compile('Out\[(\d+)\]:\s?(.*)\s*'). You
28 shouldn't need to change this.
29 ipython_promptin:
30 The string to represent the IPython input prompt in the generated ReST.
31 The default is 'In [%d]:'. This expects that the line numbers are used
32 in the prompt.
33 ipython_promptout:
34
35 The string to represent the IPython prompt in the generated ReST. The
36 default is 'Out [%d]:'. This expects that the line numbers are used
37 in the prompt.
38 38
39 39 ToDo
40 40 ----
@@ -42,8 +42,6 b' ToDo'
42 42 - Turn the ad-hoc test() function into a real test suite.
43 43 - Break up ipython-specific functionality from matplotlib stuff into better
44 44 separated code.
45 - Make sure %bookmarks used internally are removed on exit.
46
47 45
48 46 Authors
49 47 -------
@@ -51,6 +49,7 b' Authors'
51 49 - John D Hunter: orignal author.
52 50 - Fernando Perez: refactoring, documentation, cleanups, port to 0.11.
53 51 - VΓ‘clavΕ milauer <eudoxos-AT-arcig.cz>: Prompt generalizations.
52 - Skipper Seabold, refactoring, cleanups, pure python addition
54 53 """
55 54
56 55 #-----------------------------------------------------------------------------
@@ -62,6 +61,7 b' import cStringIO'
62 61 import os
63 62 import re
64 63 import sys
64 import tempfile
65 65
66 66 # To keep compatibility with various python versions
67 67 try:
@@ -73,34 +73,26 b' except ImportError:'
73 73 import matplotlib
74 74 import sphinx
75 75 from docutils.parsers.rst import directives
76 from docutils import nodes
77 from sphinx.util.compat import Directive
76 78
77 79 matplotlib.use('Agg')
78 80
79 81 # Our own
80 82 from IPython import Config, InteractiveShell
81 from IPython.utils.io import Term
83 from IPython.core.profiledir import ProfileDir
84 from IPython.utils import io
82 85
83 86 #-----------------------------------------------------------------------------
84 87 # Globals
85 88 #-----------------------------------------------------------------------------
86
87 sphinx_version = sphinx.__version__.split(".")
88 # The split is necessary for sphinx beta versions where the string is
89 # '6b1'
90 sphinx_version = tuple([int(re.split('[a-z]', x)[0])
91 for x in sphinx_version[:2]])
92
89 # for tokenizing blocks
93 90 COMMENT, INPUT, OUTPUT = range(3)
94 CONFIG = Config()
95 rgxin = re.compile('In \[(\d+)\]:\s?(.*)\s*')
96 rgxout = re.compile('Out\[(\d+)\]:\s?(.*)\s*')
97 fmtin = 'In [%d]:'
98 fmtout = 'Out[%d]:'
99 91
100 92 #-----------------------------------------------------------------------------
101 93 # Functions and class declarations
102 94 #-----------------------------------------------------------------------------
103 def block_parser(part):
95 def block_parser(part, rgxin, rgxout, fmtin, fmtout):
104 96 """
105 97 part is a string of ipython text, comprised of at most one
106 98 input, one ouput, comments, and blank lines. The block parser
@@ -194,20 +186,13 b' def block_parser(part):'
194 186
195 187 return block
196 188
197
198 189 class EmbeddedSphinxShell(object):
199 190 """An embedded IPython instance to run inside Sphinx"""
200 191
201 192 def __init__(self):
202 193
203 194 self.cout = cStringIO.StringIO()
204 Term.cout = self.cout
205 Term.cerr = self.cout
206 195
207 # For debugging, so we can see normal output, use this:
208 # from IPython.utils.io import Tee
209 #Term.cout = Tee(self.cout, channel='stdout') # dbg
210 #Term.cerr = Tee(self.cout, channel='stderr') # dbg
211 196
212 197 # Create config object for IPython
213 198 config = Config()
@@ -219,14 +204,28 b' class EmbeddedSphinxShell(object):'
219 204 config.InteractiveShell.autoindent = False
220 205 config.InteractiveShell.colors = 'NoColor'
221 206
207 # create a profile so instance history isn't saved
208 tmp_profile_dir = tempfile.mkdtemp(prefix='profile_')
209 profname = 'auto_profile_sphinx_build'
210 pdir = os.path.join(tmp_profile_dir,profname)
211 profile = ProfileDir.create_profile_dir(pdir)
212
222 213 # Create and initialize ipython, but don't start its mainloop
223 IP = InteractiveShell.instance(config=config)
214 IP = InteractiveShell.instance(config=config, profile_dir=profile)
215 # io.stdout redirect must be done *after* instantiating InteractiveShell
216 io.stdout = self.cout
217 io.stderr = self.cout
218
219 # For debugging, so we can see normal output, use this:
220 #from IPython.utils.io import Tee
221 #io.stdout = Tee(self.cout, channel='stdout') # dbg
222 #io.stderr = Tee(self.cout, channel='stderr') # dbg
224 223
225 224 # Store a few parts of IPython we'll need.
226 225 self.IP = IP
227 226 self.user_ns = self.IP.user_ns
228 227 self.user_global_ns = self.IP.user_global_ns
229
228
230 229 self.input = ''
231 230 self.output = ''
232 231
@@ -238,27 +237,61 b' class EmbeddedSphinxShell(object):'
238 237 # pyplot as plt so we can make a call to the plt.gcf().savefig
239 238 self._pyplot_imported = False
240 239
241 # we need bookmark the current dir first so we can save
242 # relative to it
243 self.process_input_line('bookmark ipy_basedir')
240 def clear_cout(self):
244 241 self.cout.seek(0)
245 242 self.cout.truncate(0)
246 243
247 def process_input_line(self, line):
244 def process_input_line(self, line, store_history=True):
248 245 """process the input, capturing stdout"""
249 246 #print "input='%s'"%self.input
250 247 stdout = sys.stdout
248 splitter = self.IP.input_splitter
251 249 try:
252 250 sys.stdout = self.cout
253 self.IP.push_line(line)
251 splitter.push(line)
252 more = splitter.push_accepts_more()
253 if not more:
254 source_raw = splitter.source_raw_reset()[1]
255 self.IP.run_cell(source_raw, store_history=store_history)
254 256 finally:
255 257 sys.stdout = stdout
256 258
259 def process_image(self, decorator):
260 """
261 # build out an image directive like
262 # .. image:: somefile.png
263 # :width 4in
264 #
265 # from an input like
266 # savefig somefile.png width=4in
267 """
268 savefig_dir = self.savefig_dir
269 source_dir = self.source_dir
270 saveargs = decorator.split(' ')
271 filename = saveargs[1]
272 # insert relative path to image file in source
273 outfile = os.path.relpath(os.path.join(savefig_dir,filename),
274 source_dir)
275
276 imagerows = ['.. image:: %s'%outfile]
277
278 for kwarg in saveargs[2:]:
279 arg, val = kwarg.split('=')
280 arg = arg.strip()
281 val = val.strip()
282 imagerows.append(' :%s: %s'%(arg, val))
283
284 image_file = os.path.basename(outfile) # only return file name
285 image_directive = '\n'.join(imagerows)
286 return image_file, image_directive
287
288
257 289 # Callbacks for each type of token
258 290 def process_input(self, data, input_prompt, lineno):
259 291 """Process data block for INPUT token."""
260 292 decorator, input, rest = data
261 293 image_file = None
294 image_directive = None
262 295 #print 'INPUT:', data # dbg
263 296 is_verbatim = decorator=='@verbatim' or self.is_verbatim
264 297 is_doctest = decorator=='@doctest' or self.is_doctest
@@ -272,48 +305,31 b' class EmbeddedSphinxShell(object):'
272 305 Nc = len(continuation)
273 306
274 307 if is_savefig:
275 saveargs = decorator.split(' ')
276 filename = saveargs[1]
277 outfile = os.path.join('_static/%s'%filename)
278 # build out an image directive like
279 # .. image:: somefile.png
280 # :width 4in
281 #
282 # from an input like
283 # savefig somefile.png width=4in
284 imagerows = ['.. image:: %s'%outfile]
285
286 for kwarg in saveargs[2:]:
287 arg, val = kwarg.split('=')
288 arg = arg.strip()
289 val = val.strip()
290 imagerows.append(' :%s: %s'%(arg, val))
291
292 image_file = outfile
293 image_directive = '\n'.join(imagerows)
294
295 # TODO: can we get "rest" from ipython
296 #self.process_input_line('\n'.join(input_lines))
308 image_file, image_directive = self.process_image(decorator)
297 309
298 310 ret = []
299 311 is_semicolon = False
312 store_history = True
300 313
301 314 for i, line in enumerate(input_lines):
302 315 if line.endswith(';'):
303 316 is_semicolon = True
317 if is_semicolon or is_suppress:
318 store_history = False
304 319
305 320 if i==0:
306 321 # process the first input line
307 322 if is_verbatim:
308 323 self.process_input_line('')
324 self.IP.execution_count += 1 # increment it anyway
309 325 else:
310 326 # only submit the line in non-verbatim mode
311 self.process_input_line(line)
327 self.process_input_line(line, store_history=store_history)
312 328 formatted_line = '%s %s'%(input_prompt, line)
313 329 else:
314 330 # process a continuation line
315 331 if not is_verbatim:
316 self.process_input_line(line)
332 self.process_input_line(line, store_history=store_history)
317 333
318 334 formatted_line = '%s %s'%(continuation, line)
319 335
@@ -334,7 +350,8 b' class EmbeddedSphinxShell(object):'
334 350 ret.append(output)
335 351
336 352 self.cout.truncate(0)
337 return ret, input_lines, output, is_doctest, image_file
353 return (ret, input_lines, output, is_doctest, image_file,
354 image_directive)
338 355 #print 'OUTPUT', output # dbg
339 356
340 357 def process_output(self, data, output_prompt,
@@ -345,16 +362,19 b' class EmbeddedSphinxShell(object):'
345 362 found = output
346 363 if found is not None:
347 364 found = found.strip()
348
365
349 366 # XXX - fperez: in 0.11, 'output' never comes with the prompt
350 367 # in it, just the actual output text. So I think all this code
351 368 # can be nuked...
352 ## ind = found.find(output_prompt)
353 ## if ind<0:
354 ## e='output prompt="%s" does not match out line=%s' % \
355 ## (output_prompt, found)
356 ## raise RuntimeError(e)
357 ## found = found[len(output_prompt):].strip()
369
370 # the above comment does not appear to be accurate... (minrk)
371
372 ind = found.find(output_prompt)
373 if ind<0:
374 e='output prompt="%s" does not match out line=%s' % \
375 (output_prompt, found)
376 raise RuntimeError(e)
377 found = found[len(output_prompt):].strip()
358 378
359 379 if found!=submitted:
360 380 e = ('doctest failure for input_lines="%s" with '
@@ -364,36 +384,45 b' class EmbeddedSphinxShell(object):'
364 384 #print 'doctest PASSED for input_lines="%s" with found_output="%s" and submitted output="%s"'%(input_lines, found, submitted)
365 385
366 386 def process_comment(self, data):
367 """Process data block for COMMENT token."""
387 """Process data fPblock for COMMENT token."""
368 388 if not self.is_suppress:
369 389 return [data]
370 390
391 def save_image(self, image_file):
392 """
393 Saves the image file to disk.
394 """
395 self.ensure_pyplot()
396 command = 'plt.gcf().savefig("%s")'%image_file
397 #print 'SAVEFIG', command # dbg
398 self.process_input_line('bookmark ipy_thisdir', store_history=False)
399 self.process_input_line('cd -b ipy_savedir', store_history=False)
400 self.process_input_line(command, store_history=False)
401 self.process_input_line('cd -b ipy_thisdir', store_history=False)
402 self.process_input_line('bookmark -d ipy_thisdir', store_history=False)
403 self.clear_cout()
404
405
371 406 def process_block(self, block):
372 407 """
373 408 process block from the block_parser and return a list of processed lines
374 409 """
375
376 410 ret = []
377 411 output = None
378 412 input_lines = None
413 lineno = self.IP.execution_count
379 414
380 m = rgxin.match(str(self.IP.outputcache.prompt1).strip())
381 lineno = int(m.group(1))
382
383 input_prompt = fmtin%lineno
384 output_prompt = fmtout%lineno
415 input_prompt = self.promptin%lineno
416 output_prompt = self.promptout%lineno
385 417 image_file = None
386 418 image_directive = None
387 # XXX - This needs a second refactor. There's too much state being
388 # held globally, which makes for a very awkward interface and large,
389 # hard to test functions. I've already broken this up at least into
390 # three separate processors to isolate the logic better, but this only
391 # serves to highlight the coupling. Next we need to clean it up...
419
392 420 for token, data in block:
393 421 if token==COMMENT:
394 422 out_data = self.process_comment(data)
395 423 elif token==INPUT:
396 out_data, input_lines, output, is_doctest, image_file= \
424 (out_data, input_lines, output, is_doctest, image_file,
425 image_directive) = \
397 426 self.process_input(data, input_prompt, lineno)
398 427 elif token==OUTPUT:
399 428 out_data = \
@@ -403,88 +432,235 b' class EmbeddedSphinxShell(object):'
403 432 if out_data:
404 433 ret.extend(out_data)
405 434
435 # save the image files
406 436 if image_file is not None:
407 self.ensure_pyplot()
408 command = 'plt.gcf().savefig("%s")'%image_file
409 print 'SAVEFIG', command # dbg
410 self.process_input_line('bookmark ipy_thisdir')
411 self.process_input_line('cd -b ipy_basedir')
412 self.process_input_line(command)
413 self.process_input_line('cd -b ipy_thisdir')
414 self.cout.seek(0)
415 self.cout.truncate(0)
437 self.save_image(image_file)
438
416 439 return ret, image_directive
417 440
418 441 def ensure_pyplot(self):
419 442 if self._pyplot_imported:
420 443 return
421 self.process_input_line('import matplotlib.pyplot as plt')
444 self.process_input_line('import matplotlib.pyplot as plt',
445 store_history=False)
422 446
423 # A global instance used below. XXX: not sure why this can't be created inside
424 # ipython_directive itself.
425 shell = EmbeddedSphinxShell()
447 def process_pure_python(self, content):
448 """
449 content is a list of strings. it is unedited directive conent
450
451 This runs it line by line in the InteractiveShell, prepends
452 prompts as needed capturing stderr and stdout, then returns
453 the content as a list as if it were ipython code
454 """
455 output = []
456 savefig = False # keep up with this to clear figure
457 multiline = False # to handle line continuation
458 fmtin = self.promptin
459
460 for lineno, line in enumerate(content):
461
462 line_stripped = line.strip()
463
464 if not len(line):
465 output.append(line) # preserve empty lines in output
466 continue
467
468 # handle decorators
469 if line_stripped.startswith('@'):
470 output.extend([line])
471 if 'savefig' in line:
472 savefig = True # and need to clear figure
473 continue
474
475 # handle comments
476 if line_stripped.startswith('#'):
477 output.extend([line])
478 continue
479
480 # deal with multilines
481 if not multiline: # not currently on a multiline
482
483 if line_stripped.endswith('\\'): # now we are
484 multiline = True
485 cont_len = len(str(lineno)) + 2
486 line_to_process = line.strip('\\')
487 output.extend([u"%s %s" % (fmtin%lineno,line)])
488 continue
489 else: # no we're still not
490 line_to_process = line.strip('\\')
491 else: # we are currently on a multiline
492 line_to_process += line.strip('\\')
493 if line_stripped.endswith('\\'): # and we still are
494 continuation = '.' * cont_len
495 output.extend([(u' %s: '+line_stripped) % continuation])
496 continue
497 # else go ahead and run this multiline then carry on
498
499 # get output of line
500 self.process_input_line(unicode(line_to_process.strip()),
501 store_history=False)
502 out_line = self.cout.getvalue()
503 self.clear_cout()
504
505 # clear current figure if plotted
506 if savefig:
507 self.ensure_pyplot()
508 self.process_input_line('plt.clf()', store_history=False)
509 self.clear_cout()
510 savefig = False
511
512 # line numbers don't actually matter, they're replaced later
513 if not multiline:
514 in_line = u"%s %s" % (fmtin%lineno,line)
515
516 output.extend([in_line])
517 else:
518 output.extend([(u' %s: '+line_stripped) % continuation])
519 multiline = False
520 if len(out_line):
521 output.extend([out_line])
522 output.extend([u''])
523
524 return output
525
526 class IpythonDirective(Directive):
527
528 has_content = True
529 required_arguments = 0
530 optional_arguments = 4 # python, suppress, verbatim, doctest
531 final_argumuent_whitespace = True
532 option_spec = { 'python': directives.unchanged,
533 'suppress' : directives.flag,
534 'verbatim' : directives.flag,
535 'doctest' : directives.flag,
536 }
426 537
427 def reconfig_shell():
428 """Called after setting module-level variables to re-instantiate
429 with the set values (since shell is instantiated first at import-time
430 when module variables have default values)"""
431 global shell
432 538 shell = EmbeddedSphinxShell()
433 539
540 def get_config_options(self):
541 # contains sphinx configuration variables
542 config = self.state.document.settings.env.config
543
544 # get config variables to set figure output directory
545 confdir = self.state.document.settings.env.app.confdir
546 savefig_dir = config.ipython_savefig_dir
547 source_dir = os.path.dirname(self.state.document.current_source)
548 if savefig_dir is None:
549 savefig_dir = config.html_static_path
550 if isinstance(savefig_dir, list):
551 savefig_dir = savefig_dir[0] # safe to assume only one path?
552 savefig_dir = os.path.join(confdir, savefig_dir)
553
554 # get regex and prompt stuff
555 rgxin = config.ipython_rgxin
556 rgxout = config.ipython_rgxout
557 promptin = config.ipython_promptin
558 promptout = config.ipython_promptout
559
560 return savefig_dir, source_dir, rgxin, rgxout, promptin, promptout
561
562 def setup(self):
563 # get config values
564 (savefig_dir, source_dir, rgxin,
565 rgxout, promptin, promptout) = self.get_config_options()
566
567 # and attach to shell so we don't have to pass them around
568 self.shell.rgxin = rgxin
569 self.shell.rgxout = rgxout
570 self.shell.promptin = promptin
571 self.shell.promptout = promptout
572 self.shell.savefig_dir = savefig_dir
573 self.shell.source_dir = source_dir
434 574
435 def ipython_directive(name, arguments, options, content, lineno,
436 content_offset, block_text, state, state_machine,
437 ):
575 # setup bookmark for saving figures directory
438 576
439 debug = ipython_directive.DEBUG
440 shell.is_suppress = options.has_key('suppress')
441 shell.is_doctest = options.has_key('doctest')
442 shell.is_verbatim = options.has_key('verbatim')
577 self.shell.process_input_line('bookmark ipy_savedir %s'%savefig_dir,
578 store_history=False)
579 self.shell.clear_cout()
443 580
444 #print 'ipy', shell.is_suppress, options
445 parts = '\n'.join(content).split('\n\n')
446 lines = ['.. sourcecode:: ipython', '']
581 return rgxin, rgxout, promptin, promptout
447 582
448 figures = []
449 for part in parts:
450 block = block_parser(part)
451 583
452 if len(block):
453 rows, figure = shell.process_block(block)
454 for row in rows:
455 lines.extend([' %s'%line for line in row.split('\n')])
584 def teardown(self):
585 # delete last bookmark
586 self.shell.process_input_line('bookmark -d ipy_savedir',
587 store_history=False)
588 self.shell.clear_cout()
456 589
457 if figure is not None:
458 figures.append(figure)
590 def run(self):
591 debug = False
459 592
460 for figure in figures:
461 lines.append('')
462 lines.extend(figure.split('\n'))
463 lines.append('')
593 #TODO, any reason block_parser can't be a method of embeddable shell
594 # then we wouldn't have to carry these around
595 rgxin, rgxout, promptin, promptout = self.setup()
464 596
465 #print lines
466 if len(lines)>2:
467 if debug:
468 print '\n'.join(lines)
469 else:
470 #print 'INSERTING %d lines'%len(lines)
471 state_machine.insert_input(
472 lines, state_machine.input_lines.source(0))
597 options = self.options
598 self.shell.is_suppress = 'suppress' in options
599 self.shell.is_doctest = 'doctest' in options
600 self.shell.is_verbatim = 'verbatim' in options
473 601
474 return []
475 602
476 ipython_directive.DEBUG = False
477 ipython_directive.DEBUG = True # dbg
603 # handle pure python code
604 if 'python' in self.arguments:
605 content = self.content
606 self.content = self.shell.process_pure_python(content)
607
608 parts = '\n'.join(self.content).split('\n\n')
609
610 lines = ['.. code-block:: ipython','']
611 figures = []
612
613 for part in parts:
614
615 block = block_parser(part, rgxin, rgxout, promptin, promptout)
616
617 if len(block):
618 rows, figure = self.shell.process_block(block)
619 for row in rows:
620 lines.extend([' %s'%line for line in row.split('\n')])
621
622 if figure is not None:
623 figures.append(figure)
624
625 #text = '\n'.join(lines)
626 #figs = '\n'.join(figures)
627
628 for figure in figures:
629 lines.append('')
630 lines.extend(figure.split('\n'))
631 lines.append('')
632
633 #print lines
634 if len(lines)>2:
635 if debug:
636 print '\n'.join(lines)
637 else: #NOTE: this raises some errors, what's it for?
638 #print 'INSERTING %d lines'%len(lines)
639 self.state_machine.insert_input(
640 lines, self.state_machine.input_lines.source(0))
641
642 text = '\n'.join(lines)
643 txtnode = nodes.literal_block(text, text)
644 txtnode['language'] = 'ipython'
645 #imgnode = nodes.image(figs)
646
647 # cleanup
648 self.teardown()
649
650 return []#, imgnode]
478 651
479 652 # Enable as a proper Sphinx directive
480 653 def setup(app):
481 654 setup.app = app
482 options = {'suppress': directives.flag,
483 'doctest': directives.flag,
484 'verbatim': directives.flag,
485 }
486 655
487 app.add_directive('ipython', ipython_directive, True, (0, 2, 0), **options)
656 app.add_directive('ipython', IpythonDirective)
657 app.add_config_value('ipython_savefig_dir', None, True)
658 app.add_config_value('ipython_rgxin',
659 re.compile('In \[(\d+)\]:\s?(.*)\s*'), True)
660 app.add_config_value('ipython_rgxout',
661 re.compile('Out\[(\d+)\]:\s?(.*)\s*'), True)
662 app.add_config_value('ipython_promptin', 'In [%d]:', True)
663 app.add_config_value('ipython_promptout', 'Out[%d]:', True)
488 664
489 665
490 666 # Simple smoke test, needs to be converted to a proper automatic test.
@@ -507,7 +683,7 b" In [3]: im = imread('stinkbug.png')"
507 683 @savefig mystinkbug.png width=4in
508 684 In [4]: imshow(im)
509 685 Out[4]: <matplotlib.image.AxesImage object at 0x39ea850>
510
686
511 687 """,
512 688 r"""
513 689
@@ -542,7 +718,7 b' In [133]: import numpy.random'
542 718 In [134]: numpy.random.seed(2358)
543 719
544 720 @doctest
545 In [135]: np.random.rand(10,2)
721 In [135]: numpy.random.rand(10,2)
546 722 Out[135]:
547 723 array([[ 0.64524308, 0.59943846],
548 724 [ 0.47102322, 0.8715456 ],
@@ -615,6 +791,8 b' In [153]: grid(True)'
615 791
616 792 """,
617 793 ]
794 # skip local-file depending first example:
795 examples = examples[1:]
618 796
619 797 #ipython_directive.DEBUG = True # dbg
620 798 #options = dict(suppress=True) # dbg
General Comments 0
You need to be logged in to leave comments. Login now