##// END OF EJS Templates
Fix imports
Skipper Seabold -
Show More
@@ -1,812 +1,813 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Sphinx directive to support embedded IPython code.
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 6 all prompts renumbered sequentially. It also allows you to input code as a pure
7 7 python input by giving the argument python to the directive. The output looks
8 8 like an interactive ipython section.
9 9
10 10 To enable this directive, simply list it in your Sphinx ``conf.py`` file
11 11 (making sure the directory where you placed it is visible to sphinx, as is
12 12 needed for all Sphinx directives).
13 13
14 14 By default this directive assumes that your prompts are unchanged IPython ones,
15 15 but this can be customized. The configurable options that can be placed in
16 16 conf.py are
17 17
18 18 ipython_savefig_dir:
19 19 The directory in which to save the figures. This is relative to the
20 20 Sphinx source directory. The default is `html_static_path`.
21 21 ipython_rgxin:
22 22 The compiled regular expression to denote the start of IPython input
23 23 lines. The default is re.compile('In \[(\d+)\]:\s?(.*)\s*'). You
24 24 shouldn't need to change this.
25 25 ipython_rgxout:
26 26 The compiled regular expression to denote the start of IPython output
27 27 lines. The default is re.compile('Out\[(\d+)\]:\s?(.*)\s*'). You
28 28 shouldn't need to change this.
29 29 ipython_promptin:
30 30 The string to represent the IPython input prompt in the generated ReST.
31 31 The default is 'In [%d]:'. This expects that the line numbers are used
32 32 in the prompt.
33 33 ipython_promptout:
34 34
35 35 The string to represent the IPython prompt in the generated ReST. The
36 36 default is 'Out [%d]:'. This expects that the line numbers are used
37 37 in the prompt.
38 38
39 39 ToDo
40 40 ----
41 41
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 45
46 46 Authors
47 47 -------
48 48
49 49 - John D Hunter: orignal author.
50 50 - Fernando Perez: refactoring, documentation, cleanups, port to 0.11.
51 51 - VΓ‘clavΕ milauer <eudoxos-AT-arcig.cz>: Prompt generalizations.
52 52 - Skipper Seabold, refactoring, cleanups, pure python addition
53 53 """
54 54
55 55 #-----------------------------------------------------------------------------
56 56 # Imports
57 57 #-----------------------------------------------------------------------------
58 58
59 59 # Stdlib
60 60 import cStringIO
61 61 import os
62 62 import re
63 63 import sys
64 64 import tempfile
65 import ast
65 66
66 67 # To keep compatibility with various python versions
67 68 try:
68 69 from hashlib import md5
69 70 except ImportError:
70 71 from md5 import md5
71 72
72 73 # Third-party
73 74 import matplotlib
74 75 import sphinx
75 76 from docutils.parsers.rst import directives
76 77 from docutils import nodes
77 78 from sphinx.util.compat import Directive
78 79
79 80 matplotlib.use('Agg')
80 81
81 82 # Our own
82 83 from IPython import Config, InteractiveShell
83 84 from IPython.core.profiledir import ProfileDir
84 85 from IPython.utils import io
85 86
86 87 #-----------------------------------------------------------------------------
87 88 # Globals
88 89 #-----------------------------------------------------------------------------
89 90 # for tokenizing blocks
90 91 COMMENT, INPUT, OUTPUT = range(3)
91 92
92 93 #-----------------------------------------------------------------------------
93 94 # Functions and class declarations
94 95 #-----------------------------------------------------------------------------
95 96 def block_parser(part, rgxin, rgxout, fmtin, fmtout):
96 97 """
97 98 part is a string of ipython text, comprised of at most one
98 99 input, one ouput, comments, and blank lines. The block parser
99 100 parses the text into a list of::
100 101
101 102 blocks = [ (TOKEN0, data0), (TOKEN1, data1), ...]
102 103
103 104 where TOKEN is one of [COMMENT | INPUT | OUTPUT ] and
104 105 data is, depending on the type of token::
105 106
106 107 COMMENT : the comment string
107 108
108 109 INPUT: the (DECORATOR, INPUT_LINE, REST) where
109 110 DECORATOR: the input decorator (or None)
110 111 INPUT_LINE: the input as string (possibly multi-line)
111 112 REST : any stdout generated by the input line (not OUTPUT)
112 113
113 114
114 115 OUTPUT: the output string, possibly multi-line
115 116 """
116 117
117 118 block = []
118 119 lines = part.split('\n')
119 120 N = len(lines)
120 121 i = 0
121 122 decorator = None
122 123 while 1:
123 124
124 125 if i==N:
125 126 # nothing left to parse -- the last line
126 127 break
127 128
128 129 line = lines[i]
129 130 i += 1
130 131 line_stripped = line.strip()
131 132 if line_stripped.startswith('#'):
132 133 block.append((COMMENT, line))
133 134 continue
134 135
135 136 if line_stripped.startswith('@'):
136 137 # we're assuming at most one decorator -- may need to
137 138 # rethink
138 139 decorator = line_stripped
139 140 continue
140 141
141 142 # does this look like an input line?
142 143 matchin = rgxin.match(line)
143 144 if matchin:
144 145 lineno, inputline = int(matchin.group(1)), matchin.group(2)
145 146
146 147 # the ....: continuation string
147 148 continuation = ' %s:'%''.join(['.']*(len(str(lineno))+2))
148 149 Nc = len(continuation)
149 150 # input lines can continue on for more than one line, if
150 151 # we have a '\' line continuation char or a function call
151 152 # echo line 'print'. The input line can only be
152 153 # terminated by the end of the block or an output line, so
153 154 # we parse out the rest of the input line if it is
154 155 # multiline as well as any echo text
155 156
156 157 rest = []
157 158 while i<N:
158 159
159 160 # look ahead; if the next line is blank, or a comment, or
160 161 # an output line, we're done
161 162
162 163 nextline = lines[i]
163 164 matchout = rgxout.match(nextline)
164 165 #print "nextline=%s, continuation=%s, starts=%s"%(nextline, continuation, nextline.startswith(continuation))
165 166 if matchout or nextline.startswith('#'):
166 167 break
167 168 elif nextline.startswith(continuation):
168 169 inputline += '\n' + nextline[Nc:]
169 170 else:
170 171 rest.append(nextline)
171 172 i+= 1
172 173
173 174 block.append((INPUT, (decorator, inputline, '\n'.join(rest))))
174 175 continue
175 176
176 177 # if it looks like an output line grab all the text to the end
177 178 # of the block
178 179 matchout = rgxout.match(line)
179 180 if matchout:
180 181 lineno, output = int(matchout.group(1)), matchout.group(2)
181 182 if i<N-1:
182 183 output = '\n'.join([output] + lines[i:])
183 184
184 185 block.append((OUTPUT, output))
185 186 break
186 187
187 188 return block
188 189
189 190 class EmbeddedSphinxShell(object):
190 191 """An embedded IPython instance to run inside Sphinx"""
191 192
192 193 def __init__(self):
193 194
194 195 self.cout = cStringIO.StringIO()
195 196
196 197
197 198 # Create config object for IPython
198 199 config = Config()
199 200 config.Global.display_banner = False
200 201 config.Global.exec_lines = ['import numpy as np',
201 202 'from pylab import *'
202 203 ]
203 204 config.InteractiveShell.autocall = False
204 205 config.InteractiveShell.autoindent = False
205 206 config.InteractiveShell.colors = 'NoColor'
206 207
207 208 # create a profile so instance history isn't saved
208 209 tmp_profile_dir = tempfile.mkdtemp(prefix='profile_')
209 210 profname = 'auto_profile_sphinx_build'
210 211 pdir = os.path.join(tmp_profile_dir,profname)
211 212 profile = ProfileDir.create_profile_dir(pdir)
212 213
213 214 # Create and initialize ipython, but don't start its mainloop
214 215 IP = InteractiveShell.instance(config=config, profile_dir=profile)
215 216 # io.stdout redirect must be done *after* instantiating InteractiveShell
216 217 io.stdout = self.cout
217 218 io.stderr = self.cout
218 219
219 220 # For debugging, so we can see normal output, use this:
220 221 #from IPython.utils.io import Tee
221 222 #io.stdout = Tee(self.cout, channel='stdout') # dbg
222 223 #io.stderr = Tee(self.cout, channel='stderr') # dbg
223 224
224 225 # Store a few parts of IPython we'll need.
225 226 self.IP = IP
226 227 self.user_ns = self.IP.user_ns
227 228 self.user_global_ns = self.IP.user_global_ns
228 229
229 230 self.input = ''
230 231 self.output = ''
231 232
232 233 self.is_verbatim = False
233 234 self.is_doctest = False
234 235 self.is_suppress = False
235 236
236 237 # on the first call to the savefig decorator, we'll import
237 238 # pyplot as plt so we can make a call to the plt.gcf().savefig
238 239 self._pyplot_imported = False
239 240
240 241 def clear_cout(self):
241 242 self.cout.seek(0)
242 243 self.cout.truncate(0)
243 244
244 245 def process_input_line(self, line, store_history=True):
245 246 """process the input, capturing stdout"""
246 247 #print "input='%s'"%self.input
247 248 stdout = sys.stdout
248 249 splitter = self.IP.input_splitter
249 250 try:
250 251 sys.stdout = self.cout
251 252 splitter.push(line)
252 253 more = splitter.push_accepts_more()
253 254 if not more:
254 255 source_raw = splitter.source_raw_reset()[1]
255 256 self.IP.run_cell(source_raw, store_history=store_history)
256 257 finally:
257 258 sys.stdout = stdout
258 259
259 260 def process_image(self, decorator):
260 261 """
261 262 # build out an image directive like
262 263 # .. image:: somefile.png
263 264 # :width 4in
264 265 #
265 266 # from an input like
266 267 # savefig somefile.png width=4in
267 268 """
268 269 savefig_dir = self.savefig_dir
269 270 source_dir = self.source_dir
270 271 saveargs = decorator.split(' ')
271 272 filename = saveargs[1]
272 273 # insert relative path to image file in source
273 274 outfile = os.path.relpath(os.path.join(savefig_dir,filename),
274 275 source_dir)
275 276
276 277 imagerows = ['.. image:: %s'%outfile]
277 278
278 279 for kwarg in saveargs[2:]:
279 280 arg, val = kwarg.split('=')
280 281 arg = arg.strip()
281 282 val = val.strip()
282 283 imagerows.append(' :%s: %s'%(arg, val))
283 284
284 285 image_file = os.path.basename(outfile) # only return file name
285 286 image_directive = '\n'.join(imagerows)
286 287 return image_file, image_directive
287 288
288 289
289 290 # Callbacks for each type of token
290 291 def process_input(self, data, input_prompt, lineno):
291 292 """Process data block for INPUT token."""
292 293 decorator, input, rest = data
293 294 image_file = None
294 295 image_directive = None
295 296 #print 'INPUT:', data # dbg
296 297 is_verbatim = decorator=='@verbatim' or self.is_verbatim
297 298 is_doctest = decorator=='@doctest' or self.is_doctest
298 299 is_suppress = decorator=='@suppress' or self.is_suppress
299 300 is_savefig = decorator is not None and \
300 301 decorator.startswith('@savefig')
301 302
302 303 input_lines = input.split('\n')
303 304 if len(input_lines) > 1:
304 305 if input_lines[-1] != "":
305 306 input_lines.append('') # make sure there's a blank line
306 307 # so splitter buffer gets reset
307 308
308 309 continuation = ' %s:'%''.join(['.']*(len(str(lineno))+2))
309 310 Nc = len(continuation)
310 311
311 312 if is_savefig:
312 313 image_file, image_directive = self.process_image(decorator)
313 314
314 315 ret = []
315 316 is_semicolon = False
316 317 store_history = True
317 318
318 319 for i, line in enumerate(input_lines):
319 320 if line.endswith(';'):
320 321 is_semicolon = True
321 322 if is_suppress:
322 323 store_history = False
323 324
324 325 if i==0:
325 326 # process the first input line
326 327 if is_verbatim:
327 328 self.process_input_line('')
328 329 self.IP.execution_count += 1 # increment it anyway
329 330 else:
330 331 # only submit the line in non-verbatim mode
331 332 self.process_input_line(line, store_history=store_history)
332 333 formatted_line = '%s %s'%(input_prompt, line)
333 334 else:
334 335 # process a continuation line
335 336 if not is_verbatim:
336 337 self.process_input_line(line, store_history=store_history)
337 338
338 339 formatted_line = '%s %s'%(continuation, line)
339 340
340 341 if not is_suppress:
341 342 ret.append(formatted_line)
342 343
343 344 if not is_suppress and len(rest.strip()) and is_verbatim:
344 345 # the "rest" is the standard output of the
345 346 # input, which needs to be added in
346 347 # verbatim mode
347 348 ret.append(rest)
348 349
349 350 self.cout.seek(0)
350 351 output = self.cout.read()
351 352 if not is_suppress and not is_semicolon:
352 353 ret.append(output)
353 354 elif is_semicolon: # get spacing right
354 355 ret.append('')
355 356
356 357 self.cout.truncate(0)
357 358 return (ret, input_lines, output, is_doctest, image_file,
358 359 image_directive)
359 360 #print 'OUTPUT', output # dbg
360 361
361 362 def process_output(self, data, output_prompt,
362 363 input_lines, output, is_doctest, image_file):
363 364 """Process data block for OUTPUT token."""
364 365 if is_doctest:
365 366 submitted = data.strip()
366 367 found = output
367 368 if found is not None:
368 369 found = found.strip()
369 370
370 371 # XXX - fperez: in 0.11, 'output' never comes with the prompt
371 372 # in it, just the actual output text. So I think all this code
372 373 # can be nuked...
373 374
374 375 # the above comment does not appear to be accurate... (minrk)
375 376
376 377 ind = found.find(output_prompt)
377 378 if ind<0:
378 379 e='output prompt="%s" does not match out line=%s' % \
379 380 (output_prompt, found)
380 381 raise RuntimeError(e)
381 382 found = found[len(output_prompt):].strip()
382 383
383 384 if found!=submitted:
384 385 e = ('doctest failure for input_lines="%s" with '
385 386 'found_output="%s" and submitted output="%s"' %
386 387 (input_lines, found, submitted) )
387 388 raise RuntimeError(e)
388 389 #print 'doctest PASSED for input_lines="%s" with found_output="%s" and submitted output="%s"'%(input_lines, found, submitted)
389 390
390 391 def process_comment(self, data):
391 392 """Process data fPblock for COMMENT token."""
392 393 if not self.is_suppress:
393 394 return [data]
394 395
395 396 def save_image(self, image_file):
396 397 """
397 398 Saves the image file to disk.
398 399 """
399 400 self.ensure_pyplot()
400 401 command = 'plt.gcf().savefig("%s")'%image_file
401 402 #print 'SAVEFIG', command # dbg
402 403 self.process_input_line('bookmark ipy_thisdir', store_history=False)
403 404 self.process_input_line('cd -b ipy_savedir', store_history=False)
404 405 self.process_input_line(command, store_history=False)
405 406 self.process_input_line('cd -b ipy_thisdir', store_history=False)
406 407 self.process_input_line('bookmark -d ipy_thisdir', store_history=False)
407 408 self.clear_cout()
408 409
409 410
410 411 def process_block(self, block):
411 412 """
412 413 process block from the block_parser and return a list of processed lines
413 414 """
414 415 ret = []
415 416 output = None
416 417 input_lines = None
417 418 lineno = self.IP.execution_count
418 419
419 420 input_prompt = self.promptin%lineno
420 421 output_prompt = self.promptout%lineno
421 422 image_file = None
422 423 image_directive = None
423 424
424 425 for token, data in block:
425 426 if token==COMMENT:
426 427 out_data = self.process_comment(data)
427 428 elif token==INPUT:
428 429 (out_data, input_lines, output, is_doctest, image_file,
429 430 image_directive) = \
430 431 self.process_input(data, input_prompt, lineno)
431 432 elif token==OUTPUT:
432 433 out_data = \
433 434 self.process_output(data, output_prompt,
434 435 input_lines, output, is_doctest,
435 436 image_file)
436 437 if out_data:
437 438 ret.extend(out_data)
438 439
439 440 # save the image files
440 441 if image_file is not None:
441 442 self.save_image(image_file)
442 443
443 444 return ret, image_directive
444 445
445 446 def ensure_pyplot(self):
446 447 if self._pyplot_imported:
447 448 return
448 449 self.process_input_line('import matplotlib.pyplot as plt',
449 450 store_history=False)
450 451
451 452 def process_pure_python(self, content):
452 453 """
453 454 content is a list of strings. it is unedited directive conent
454 455
455 456 This runs it line by line in the InteractiveShell, prepends
456 457 prompts as needed capturing stderr and stdout, then returns
457 458 the content as a list as if it were ipython code
458 459 """
459 460 output = []
460 461 savefig = False # keep up with this to clear figure
461 462 multiline = False # to handle line continuation
462 463 multiline_start = None
463 464 fmtin = self.promptin
464 465
465 466 ct = 0
466 467
467 468 for lineno, line in enumerate(content):
468 469
469 470 line_stripped = line.strip()
470 471 if not len(line):
471 472 output.append(line)
472 473 continue
473 474
474 475 # handle decorators
475 476 if line_stripped.startswith('@'):
476 477 output.extend([line])
477 478 if 'savefig' in line:
478 479 savefig = True # and need to clear figure
479 480 continue
480 481
481 482 # handle comments
482 483 if line_stripped.startswith('#'):
483 484 output.extend([line])
484 485 continue
485 486
486 487 # deal with lines checking for multiline
487 488 continuation = u' %s:'% ''.join(['.']*(len(str(ct))+2))
488 489 if not multiline:
489 490 modified = u"%s %s" % (fmtin % ct, line_stripped)
490 491 output.append(modified)
491 492 ct += 1
492 493 try:
493 494 ast.parse(line_stripped)
494 495 output.append(u'')
495 496 except Exception: # on a multiline
496 497 multiline = True
497 498 multiline_start = lineno
498 499 if line_stripped.startswith('def '):
499 500 is_function = True
500 501 else: # still on a multiline
501 502 modified = u'%s %s' % (continuation, line)
502 503 output.append(modified)
503 504 try:
504 505 mod = ast.parse(
505 506 '\n'.join(content[multiline_start:lineno+1]))
506 507 if isinstance(mod.body[0], ast.FunctionDef):
507 508 # check to see if we have the whole function
508 509 for element in mod.body[0].body:
509 510 if isinstance(element, ast.Return):
510 511 multiline = False
511 512 else:
512 513 output.append(u'')
513 514 multiline = False
514 515 except Exception:
515 516 pass
516 517
517 518 if savefig: # clear figure if plotted
518 519 self.ensure_pyplot()
519 520 self.process_input_line('plt.clf()', store_history=False)
520 521 self.clear_cout()
521 522 savefig = False
522 523
523 524 return output
524 525
525 526 class IpythonDirective(Directive):
526 527
527 528 has_content = True
528 529 required_arguments = 0
529 530 optional_arguments = 4 # python, suppress, verbatim, doctest
530 531 final_argumuent_whitespace = True
531 532 option_spec = { 'python': directives.unchanged,
532 533 'suppress' : directives.flag,
533 534 'verbatim' : directives.flag,
534 535 'doctest' : directives.flag,
535 536 }
536 537
537 538 shell = EmbeddedSphinxShell()
538 539
539 540 def get_config_options(self):
540 541 # contains sphinx configuration variables
541 542 config = self.state.document.settings.env.config
542 543
543 544 # get config variables to set figure output directory
544 545 confdir = self.state.document.settings.env.app.confdir
545 546 savefig_dir = config.ipython_savefig_dir
546 547 source_dir = os.path.dirname(self.state.document.current_source)
547 548 if savefig_dir is None:
548 549 savefig_dir = config.html_static_path
549 550 if isinstance(savefig_dir, list):
550 551 savefig_dir = savefig_dir[0] # safe to assume only one path?
551 552 savefig_dir = os.path.join(confdir, savefig_dir)
552 553
553 554 # get regex and prompt stuff
554 555 rgxin = config.ipython_rgxin
555 556 rgxout = config.ipython_rgxout
556 557 promptin = config.ipython_promptin
557 558 promptout = config.ipython_promptout
558 559
559 560 return savefig_dir, source_dir, rgxin, rgxout, promptin, promptout
560 561
561 562 def setup(self):
562 563 # get config values
563 564 (savefig_dir, source_dir, rgxin,
564 565 rgxout, promptin, promptout) = self.get_config_options()
565 566
566 567 # and attach to shell so we don't have to pass them around
567 568 self.shell.rgxin = rgxin
568 569 self.shell.rgxout = rgxout
569 570 self.shell.promptin = promptin
570 571 self.shell.promptout = promptout
571 572 self.shell.savefig_dir = savefig_dir
572 573 self.shell.source_dir = source_dir
573 574
574 575 # setup bookmark for saving figures directory
575 576
576 577 self.shell.process_input_line('bookmark ipy_savedir %s'%savefig_dir,
577 578 store_history=False)
578 579 self.shell.clear_cout()
579 580
580 581 return rgxin, rgxout, promptin, promptout
581 582
582 583
583 584 def teardown(self):
584 585 # delete last bookmark
585 586 self.shell.process_input_line('bookmark -d ipy_savedir',
586 587 store_history=False)
587 588 self.shell.clear_cout()
588 589
589 590 def run(self):
590 591 debug = False
591 592
592 593 #TODO, any reason block_parser can't be a method of embeddable shell
593 594 # then we wouldn't have to carry these around
594 595 rgxin, rgxout, promptin, promptout = self.setup()
595 596
596 597 options = self.options
597 598 self.shell.is_suppress = 'suppress' in options
598 599 self.shell.is_doctest = 'doctest' in options
599 600 self.shell.is_verbatim = 'verbatim' in options
600 601
601 602
602 603 # handle pure python code
603 604 if 'python' in self.arguments:
604 605 content = self.content
605 606 self.content = self.shell.process_pure_python(content)
606 607
607 608 parts = '\n'.join(self.content).split('\n\n')
608 609
609 610 lines = ['.. code-block:: ipython','']
610 611 figures = []
611 612
612 613 for part in parts:
613 614
614 615 block = block_parser(part, rgxin, rgxout, promptin, promptout)
615 616
616 617 if len(block):
617 618 rows, figure = self.shell.process_block(block)
618 619 for row in rows:
619 620 lines.extend([' %s'%line for line in row.split('\n')])
620 621
621 622 if figure is not None:
622 623 figures.append(figure)
623 624
624 625 #text = '\n'.join(lines)
625 626 #figs = '\n'.join(figures)
626 627
627 628 for figure in figures:
628 629 lines.append('')
629 630 lines.extend(figure.split('\n'))
630 631 lines.append('')
631 632
632 633 #print lines
633 634 if len(lines)>2:
634 635 if debug:
635 636 print '\n'.join(lines)
636 637 else: #NOTE: this raises some errors, what's it for?
637 638 #print 'INSERTING %d lines'%len(lines)
638 639 self.state_machine.insert_input(
639 640 lines, self.state_machine.input_lines.source(0))
640 641
641 642 text = '\n'.join(lines)
642 643 txtnode = nodes.literal_block(text, text)
643 644 txtnode['language'] = 'ipython'
644 645 #imgnode = nodes.image(figs)
645 646
646 647 # cleanup
647 648 self.teardown()
648 649
649 650 return []#, imgnode]
650 651
651 652 # Enable as a proper Sphinx directive
652 653 def setup(app):
653 654 setup.app = app
654 655
655 656 app.add_directive('ipython', IpythonDirective)
656 657 app.add_config_value('ipython_savefig_dir', None, True)
657 658 app.add_config_value('ipython_rgxin',
658 659 re.compile('In \[(\d+)\]:\s?(.*)\s*'), True)
659 660 app.add_config_value('ipython_rgxout',
660 661 re.compile('Out\[(\d+)\]:\s?(.*)\s*'), True)
661 662 app.add_config_value('ipython_promptin', 'In [%d]:', True)
662 663 app.add_config_value('ipython_promptout', 'Out[%d]:', True)
663 664
664 665
665 666 # Simple smoke test, needs to be converted to a proper automatic test.
666 667 def test():
667 668
668 669 examples = [
669 670 r"""
670 671 In [9]: pwd
671 672 Out[9]: '/home/jdhunter/py4science/book'
672 673
673 674 In [10]: cd bookdata/
674 675 /home/jdhunter/py4science/book/bookdata
675 676
676 677 In [2]: from pylab import *
677 678
678 679 In [2]: ion()
679 680
680 681 In [3]: im = imread('stinkbug.png')
681 682
682 683 @savefig mystinkbug.png width=4in
683 684 In [4]: imshow(im)
684 685 Out[4]: <matplotlib.image.AxesImage object at 0x39ea850>
685 686
686 687 """,
687 688 r"""
688 689
689 690 In [1]: x = 'hello world'
690 691
691 692 # string methods can be
692 693 # used to alter the string
693 694 @doctest
694 695 In [2]: x.upper()
695 696 Out[2]: 'HELLO WORLD'
696 697
697 698 @verbatim
698 699 In [3]: x.st<TAB>
699 700 x.startswith x.strip
700 701 """,
701 702 r"""
702 703
703 704 In [130]: url = 'http://ichart.finance.yahoo.com/table.csv?s=CROX\
704 705 .....: &d=9&e=22&f=2009&g=d&a=1&br=8&c=2006&ignore=.csv'
705 706
706 707 In [131]: print url.split('&')
707 708 ['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']
708 709
709 710 In [60]: import urllib
710 711
711 712 """,
712 713 r"""\
713 714
714 715 In [133]: import numpy.random
715 716
716 717 @suppress
717 718 In [134]: numpy.random.seed(2358)
718 719
719 720 @doctest
720 721 In [135]: numpy.random.rand(10,2)
721 722 Out[135]:
722 723 array([[ 0.64524308, 0.59943846],
723 724 [ 0.47102322, 0.8715456 ],
724 725 [ 0.29370834, 0.74776844],
725 726 [ 0.99539577, 0.1313423 ],
726 727 [ 0.16250302, 0.21103583],
727 728 [ 0.81626524, 0.1312433 ],
728 729 [ 0.67338089, 0.72302393],
729 730 [ 0.7566368 , 0.07033696],
730 731 [ 0.22591016, 0.77731835],
731 732 [ 0.0072729 , 0.34273127]])
732 733
733 734 """,
734 735
735 736 r"""
736 737 In [106]: print x
737 738 jdh
738 739
739 740 In [109]: for i in range(10):
740 741 .....: print i
741 742 .....:
742 743 .....:
743 744 0
744 745 1
745 746 2
746 747 3
747 748 4
748 749 5
749 750 6
750 751 7
751 752 8
752 753 9
753 754 """,
754 755
755 756 r"""
756 757
757 758 In [144]: from pylab import *
758 759
759 760 In [145]: ion()
760 761
761 762 # use a semicolon to suppress the output
762 763 @savefig test_hist.png width=4in
763 764 In [151]: hist(np.random.randn(10000), 100);
764 765
765 766
766 767 @savefig test_plot.png width=4in
767 768 In [151]: plot(np.random.randn(10000), 'o');
768 769 """,
769 770
770 771 r"""
771 772 # use a semicolon to suppress the output
772 773 In [151]: plt.clf()
773 774
774 775 @savefig plot_simple.png width=4in
775 776 In [151]: plot([1,2,3])
776 777
777 778 @savefig hist_simple.png width=4in
778 779 In [151]: hist(np.random.randn(10000), 100);
779 780
780 781 """,
781 782 r"""
782 783 # update the current fig
783 784 In [151]: ylabel('number')
784 785
785 786 In [152]: title('normal distribution')
786 787
787 788
788 789 @savefig hist_with_text.png
789 790 In [153]: grid(True)
790 791
791 792 """,
792 793 ]
793 794 # skip local-file depending first example:
794 795 examples = examples[1:]
795 796
796 797 #ipython_directive.DEBUG = True # dbg
797 798 #options = dict(suppress=True) # dbg
798 799 options = dict()
799 800 for example in examples:
800 801 content = example.split('\n')
801 802 ipython_directive('debug', arguments=None, options=options,
802 803 content=content, lineno=0,
803 804 content_offset=None, block_text=None,
804 805 state=None, state_machine=None,
805 806 )
806 807
807 808 # Run test suite as a script
808 809 if __name__=='__main__':
809 810 if not os.path.isdir('_static'):
810 811 os.mkdir('_static')
811 812 test()
812 813 print 'All OK? Check figures in _static/'
General Comments 0
You need to be logged in to leave comments. Login now