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