##// END OF EJS Templates
Fix demo.py so it uses the new get_ipython() call for global instance
Fernando Perez -
Show More
@@ -1,555 +1,556 b''
1 """Module for interactive demos using IPython.
1 """Module for interactive demos using IPython.
2
2
3 This module implements a few classes for running Python scripts interactively
3 This module implements a few classes for running Python scripts interactively
4 in IPython for demonstrations. With very simple markup (a few tags in
4 in IPython for demonstrations. With very simple markup (a few tags in
5 comments), you can control points where the script stops executing and returns
5 comments), you can control points where the script stops executing and returns
6 control to IPython.
6 control to IPython.
7
7
8
8
9 Provided classes
9 Provided classes
10 ================
10 ================
11
11
12 The classes are (see their docstrings for further details):
12 The classes are (see their docstrings for further details):
13
13
14 - Demo: pure python demos
14 - Demo: pure python demos
15
15
16 - IPythonDemo: demos with input to be processed by IPython as if it had been
16 - IPythonDemo: demos with input to be processed by IPython as if it had been
17 typed interactively (so magics work, as well as any other special syntax you
17 typed interactively (so magics work, as well as any other special syntax you
18 may have added via input prefilters).
18 may have added via input prefilters).
19
19
20 - LineDemo: single-line version of the Demo class. These demos are executed
20 - LineDemo: single-line version of the Demo class. These demos are executed
21 one line at a time, and require no markup.
21 one line at a time, and require no markup.
22
22
23 - IPythonLineDemo: IPython version of the LineDemo class (the demo is
23 - IPythonLineDemo: IPython version of the LineDemo class (the demo is
24 executed a line at a time, but processed via IPython).
24 executed a line at a time, but processed via IPython).
25
25
26 - ClearMixin: mixin to make Demo classes with less visual clutter. It
26 - ClearMixin: mixin to make Demo classes with less visual clutter. It
27 declares an empty marquee and a pre_cmd that clears the screen before each
27 declares an empty marquee and a pre_cmd that clears the screen before each
28 block (see Subclassing below).
28 block (see Subclassing below).
29
29
30 - ClearDemo, ClearIPDemo: mixin-enabled versions of the Demo and IPythonDemo
30 - ClearDemo, ClearIPDemo: mixin-enabled versions of the Demo and IPythonDemo
31 classes.
31 classes.
32
32
33
33
34 Subclassing
34 Subclassing
35 ===========
35 ===========
36
36
37 The classes here all include a few methods meant to make customization by
37 The classes here all include a few methods meant to make customization by
38 subclassing more convenient. Their docstrings below have some more details:
38 subclassing more convenient. Their docstrings below have some more details:
39
39
40 - marquee(): generates a marquee to provide visible on-screen markers at each
40 - marquee(): generates a marquee to provide visible on-screen markers at each
41 block start and end.
41 block start and end.
42
42
43 - pre_cmd(): run right before the execution of each block.
43 - pre_cmd(): run right before the execution of each block.
44
44
45 - post_cmd(): run right after the execution of each block. If the block
45 - post_cmd(): run right after the execution of each block. If the block
46 raises an exception, this is NOT called.
46 raises an exception, this is NOT called.
47
47
48
48
49 Operation
49 Operation
50 =========
50 =========
51
51
52 The file is run in its own empty namespace (though you can pass it a string of
52 The file is run in its own empty namespace (though you can pass it a string of
53 arguments as if in a command line environment, and it will see those as
53 arguments as if in a command line environment, and it will see those as
54 sys.argv). But at each stop, the global IPython namespace is updated with the
54 sys.argv). But at each stop, the global IPython namespace is updated with the
55 current internal demo namespace, so you can work interactively with the data
55 current internal demo namespace, so you can work interactively with the data
56 accumulated so far.
56 accumulated so far.
57
57
58 By default, each block of code is printed (with syntax highlighting) before
58 By default, each block of code is printed (with syntax highlighting) before
59 executing it and you have to confirm execution. This is intended to show the
59 executing it and you have to confirm execution. This is intended to show the
60 code to an audience first so you can discuss it, and only proceed with
60 code to an audience first so you can discuss it, and only proceed with
61 execution once you agree. There are a few tags which allow you to modify this
61 execution once you agree. There are a few tags which allow you to modify this
62 behavior.
62 behavior.
63
63
64 The supported tags are:
64 The supported tags are:
65
65
66 # <demo> stop
66 # <demo> stop
67
67
68 Defines block boundaries, the points where IPython stops execution of the
68 Defines block boundaries, the points where IPython stops execution of the
69 file and returns to the interactive prompt.
69 file and returns to the interactive prompt.
70
70
71 You can optionally mark the stop tag with extra dashes before and after the
71 You can optionally mark the stop tag with extra dashes before and after the
72 word 'stop', to help visually distinguish the blocks in a text editor:
72 word 'stop', to help visually distinguish the blocks in a text editor:
73
73
74 # <demo> --- stop ---
74 # <demo> --- stop ---
75
75
76
76
77 # <demo> silent
77 # <demo> silent
78
78
79 Make a block execute silently (and hence automatically). Typically used in
79 Make a block execute silently (and hence automatically). Typically used in
80 cases where you have some boilerplate or initialization code which you need
80 cases where you have some boilerplate or initialization code which you need
81 executed but do not want to be seen in the demo.
81 executed but do not want to be seen in the demo.
82
82
83 # <demo> auto
83 # <demo> auto
84
84
85 Make a block execute automatically, but still being printed. Useful for
85 Make a block execute automatically, but still being printed. Useful for
86 simple code which does not warrant discussion, since it avoids the extra
86 simple code which does not warrant discussion, since it avoids the extra
87 manual confirmation.
87 manual confirmation.
88
88
89 # <demo> auto_all
89 # <demo> auto_all
90
90
91 This tag can _only_ be in the first block, and if given it overrides the
91 This tag can _only_ be in the first block, and if given it overrides the
92 individual auto tags to make the whole demo fully automatic (no block asks
92 individual auto tags to make the whole demo fully automatic (no block asks
93 for confirmation). It can also be given at creation time (or the attribute
93 for confirmation). It can also be given at creation time (or the attribute
94 set later) to override what's in the file.
94 set later) to override what's in the file.
95
95
96 While _any_ python file can be run as a Demo instance, if there are no stop
96 While _any_ python file can be run as a Demo instance, if there are no stop
97 tags the whole file will run in a single block (no different that calling
97 tags the whole file will run in a single block (no different that calling
98 first %pycat and then %run). The minimal markup to make this useful is to
98 first %pycat and then %run). The minimal markup to make this useful is to
99 place a set of stop tags; the other tags are only there to let you fine-tune
99 place a set of stop tags; the other tags are only there to let you fine-tune
100 the execution.
100 the execution.
101
101
102 This is probably best explained with the simple example file below. You can
102 This is probably best explained with the simple example file below. You can
103 copy this into a file named ex_demo.py, and try running it via:
103 copy this into a file named ex_demo.py, and try running it via:
104
104
105 from IPython.demo import Demo
105 from IPython.demo import Demo
106 d = Demo('ex_demo.py')
106 d = Demo('ex_demo.py')
107 d() <--- Call the d object (omit the parens if you have autocall set to 2).
107 d() <--- Call the d object (omit the parens if you have autocall set to 2).
108
108
109 Each time you call the demo object, it runs the next block. The demo object
109 Each time you call the demo object, it runs the next block. The demo object
110 has a few useful methods for navigation, like again(), edit(), jump(), seek()
110 has a few useful methods for navigation, like again(), edit(), jump(), seek()
111 and back(). It can be reset for a new run via reset() or reloaded from disk
111 and back(). It can be reset for a new run via reset() or reloaded from disk
112 (in case you've edited the source) via reload(). See their docstrings below.
112 (in case you've edited the source) via reload(). See their docstrings below.
113
113
114 Note: To make this simpler to explore, a file called "demo-exercizer.py" has
114 Note: To make this simpler to explore, a file called "demo-exercizer.py" has
115 been added to the "docs/examples/core" directory. Just cd to this directory in
115 been added to the "docs/examples/core" directory. Just cd to this directory in
116 an IPython session, and type::
116 an IPython session, and type::
117
117
118 %run demo-exercizer.py
118 %run demo-exercizer.py
119
119
120 and then follow the directions.
120 and then follow the directions.
121
121
122 Example
122 Example
123 =======
123 =======
124
124
125 The following is a very simple example of a valid demo file.
125 The following is a very simple example of a valid demo file.
126
126
127 #################### EXAMPLE DEMO <ex_demo.py> ###############################
127 #################### EXAMPLE DEMO <ex_demo.py> ###############################
128 '''A simple interactive demo to illustrate the use of IPython's Demo class.'''
128 '''A simple interactive demo to illustrate the use of IPython's Demo class.'''
129
129
130 print 'Hello, welcome to an interactive IPython demo.'
130 print 'Hello, welcome to an interactive IPython demo.'
131
131
132 # The mark below defines a block boundary, which is a point where IPython will
132 # The mark below defines a block boundary, which is a point where IPython will
133 # stop execution and return to the interactive prompt. The dashes are actually
133 # stop execution and return to the interactive prompt. The dashes are actually
134 # optional and used only as a visual aid to clearly separate blocks while
134 # optional and used only as a visual aid to clearly separate blocks while
135 # editing the demo code.
135 # editing the demo code.
136 # <demo> stop
136 # <demo> stop
137
137
138 x = 1
138 x = 1
139 y = 2
139 y = 2
140
140
141 # <demo> stop
141 # <demo> stop
142
142
143 # the mark below makes this block as silent
143 # the mark below makes this block as silent
144 # <demo> silent
144 # <demo> silent
145
145
146 print 'This is a silent block, which gets executed but not printed.'
146 print 'This is a silent block, which gets executed but not printed.'
147
147
148 # <demo> stop
148 # <demo> stop
149 # <demo> auto
149 # <demo> auto
150 print 'This is an automatic block.'
150 print 'This is an automatic block.'
151 print 'It is executed without asking for confirmation, but printed.'
151 print 'It is executed without asking for confirmation, but printed.'
152 z = x+y
152 z = x+y
153
153
154 print 'z=',x
154 print 'z=',x
155
155
156 # <demo> stop
156 # <demo> stop
157 # This is just another normal block.
157 # This is just another normal block.
158 print 'z is now:', z
158 print 'z is now:', z
159
159
160 print 'bye!'
160 print 'bye!'
161 ################### END EXAMPLE DEMO <ex_demo.py> ############################
161 ################### END EXAMPLE DEMO <ex_demo.py> ############################
162 """
162 """
163
163
164 #*****************************************************************************
164 #*****************************************************************************
165 # Copyright (C) 2005-2006 Fernando Perez. <Fernando.Perez@colorado.edu>
165 # Copyright (C) 2005-2006 Fernando Perez. <Fernando.Perez@colorado.edu>
166 #
166 #
167 # Distributed under the terms of the BSD License. The full license is in
167 # Distributed under the terms of the BSD License. The full license is in
168 # the file COPYING, distributed as part of this software.
168 # the file COPYING, distributed as part of this software.
169 #
169 #
170 #*****************************************************************************
170 #*****************************************************************************
171
171
172 import exceptions
172 import exceptions
173 import os
173 import os
174 import re
174 import re
175 import shlex
175 import shlex
176 import sys
176 import sys
177
177
178 from IPython.utils.PyColorize import Parser
178 from IPython.utils.PyColorize import Parser
179 from IPython.utils.io import file_read, file_readlines, Term
179 from IPython.utils.io import file_read, file_readlines, Term
180 from IPython.utils.text import marquee
180 from IPython.utils.text import marquee
181
181
182 __all__ = ['Demo','IPythonDemo','LineDemo','IPythonLineDemo','DemoError']
182 __all__ = ['Demo','IPythonDemo','LineDemo','IPythonLineDemo','DemoError']
183
183
184 class DemoError(exceptions.Exception): pass
184 class DemoError(exceptions.Exception): pass
185
185
186 def re_mark(mark):
186 def re_mark(mark):
187 return re.compile(r'^\s*#\s+<demo>\s+%s\s*$' % mark,re.MULTILINE)
187 return re.compile(r'^\s*#\s+<demo>\s+%s\s*$' % mark,re.MULTILINE)
188
188
189 class Demo(object):
189 class Demo(object):
190
190
191 re_stop = re_mark('-*\s?stop\s?-*')
191 re_stop = re_mark('-*\s?stop\s?-*')
192 re_silent = re_mark('silent')
192 re_silent = re_mark('silent')
193 re_auto = re_mark('auto')
193 re_auto = re_mark('auto')
194 re_auto_all = re_mark('auto_all')
194 re_auto_all = re_mark('auto_all')
195
195
196 def __init__(self,src,title='',arg_str='',auto_all=None):
196 def __init__(self,src,title='',arg_str='',auto_all=None):
197 """Make a new demo object. To run the demo, simply call the object.
197 """Make a new demo object. To run the demo, simply call the object.
198
198
199 See the module docstring for full details and an example (you can use
199 See the module docstring for full details and an example (you can use
200 IPython.Demo? in IPython to see it).
200 IPython.Demo? in IPython to see it).
201
201
202 Inputs:
202 Inputs:
203
203
204 - src is either a file, or file-like object, or a
204 - src is either a file, or file-like object, or a
205 string that can be resolved to a filename.
205 string that can be resolved to a filename.
206
206
207 Optional inputs:
207 Optional inputs:
208
208
209 - title: a string to use as the demo name. Of most use when the demo
209 - title: a string to use as the demo name. Of most use when the demo
210 you are making comes from an object that has no filename, or if you
210 you are making comes from an object that has no filename, or if you
211 want an alternate denotation distinct from the filename.
211 want an alternate denotation distinct from the filename.
212
212
213 - arg_str(''): a string of arguments, internally converted to a list
213 - arg_str(''): a string of arguments, internally converted to a list
214 just like sys.argv, so the demo script can see a similar
214 just like sys.argv, so the demo script can see a similar
215 environment.
215 environment.
216
216
217 - auto_all(None): global flag to run all blocks automatically without
217 - auto_all(None): global flag to run all blocks automatically without
218 confirmation. This attribute overrides the block-level tags and
218 confirmation. This attribute overrides the block-level tags and
219 applies to the whole demo. It is an attribute of the object, and
219 applies to the whole demo. It is an attribute of the object, and
220 can be changed at runtime simply by reassigning it to a boolean
220 can be changed at runtime simply by reassigning it to a boolean
221 value.
221 value.
222 """
222 """
223 if hasattr(src, "read"):
223 if hasattr(src, "read"):
224 # It seems to be a file or a file-like object
224 # It seems to be a file or a file-like object
225 self.fobj = src
225 self.fobj = src
226 self.fname = "from a file-like object"
226 self.fname = "from a file-like object"
227 if title == '':
227 if title == '':
228 self.title = "from a file-like object"
228 self.title = "from a file-like object"
229 else:
229 else:
230 self.title = title
230 self.title = title
231 else:
231 else:
232 # Assume it's a string or something that can be converted to one
232 # Assume it's a string or something that can be converted to one
233 self.fobj = open(src)
233 self.fobj = open(src)
234 self.fname = src
234 self.fname = src
235 if title == '':
235 if title == '':
236 (filepath, filename) = os.path.split(src)
236 (filepath, filename) = os.path.split(src)
237 self.title = filename
237 self.title = filename
238 else:
238 else:
239 self.title = title
239 self.title = title
240 self.sys_argv = [src] + shlex.split(arg_str)
240 self.sys_argv = [src] + shlex.split(arg_str)
241 self.auto_all = auto_all
241 self.auto_all = auto_all
242
242
243 # get a few things from ipython. While it's a bit ugly design-wise,
243 # get a few things from ipython. While it's a bit ugly design-wise,
244 # it ensures that things like color scheme and the like are always in
244 # it ensures that things like color scheme and the like are always in
245 # sync with the ipython mode being used. This class is only meant to
245 # sync with the ipython mode being used. This class is only meant to
246 # be used inside ipython anyways, so it's OK.
246 # be used inside ipython anyways, so it's OK.
247 self.ip_ns = __IPYTHON__.user_ns
247 ip = get_ipython() # this is in builtins whenever IPython is running
248 self.ip_colorize = __IPYTHON__.pycolorize
248 self.ip_ns = ip.user_ns
249 self.ip_showtb = __IPYTHON__.showtraceback
249 self.ip_colorize = ip.pycolorize
250 self.ip_runlines = __IPYTHON__.runlines
250 self.ip_showtb = ip.showtraceback
251 self.shell = __IPYTHON__
251 self.ip_runlines = ip.runlines
252 self.shell = ip
252
253
253 # load user data and initialize data structures
254 # load user data and initialize data structures
254 self.reload()
255 self.reload()
255
256
256 def reload(self):
257 def reload(self):
257 """Reload source from disk and initialize state."""
258 """Reload source from disk and initialize state."""
258 # read data and parse into blocks
259 # read data and parse into blocks
259 self.src = self.fobj.read()
260 self.src = self.fobj.read()
260 src_b = [b.strip() for b in self.re_stop.split(self.src) if b]
261 src_b = [b.strip() for b in self.re_stop.split(self.src) if b]
261 self._silent = [bool(self.re_silent.findall(b)) for b in src_b]
262 self._silent = [bool(self.re_silent.findall(b)) for b in src_b]
262 self._auto = [bool(self.re_auto.findall(b)) for b in src_b]
263 self._auto = [bool(self.re_auto.findall(b)) for b in src_b]
263
264
264 # if auto_all is not given (def. None), we read it from the file
265 # if auto_all is not given (def. None), we read it from the file
265 if self.auto_all is None:
266 if self.auto_all is None:
266 self.auto_all = bool(self.re_auto_all.findall(src_b[0]))
267 self.auto_all = bool(self.re_auto_all.findall(src_b[0]))
267 else:
268 else:
268 self.auto_all = bool(self.auto_all)
269 self.auto_all = bool(self.auto_all)
269
270
270 # Clean the sources from all markup so it doesn't get displayed when
271 # Clean the sources from all markup so it doesn't get displayed when
271 # running the demo
272 # running the demo
272 src_blocks = []
273 src_blocks = []
273 auto_strip = lambda s: self.re_auto.sub('',s)
274 auto_strip = lambda s: self.re_auto.sub('',s)
274 for i,b in enumerate(src_b):
275 for i,b in enumerate(src_b):
275 if self._auto[i]:
276 if self._auto[i]:
276 src_blocks.append(auto_strip(b))
277 src_blocks.append(auto_strip(b))
277 else:
278 else:
278 src_blocks.append(b)
279 src_blocks.append(b)
279 # remove the auto_all marker
280 # remove the auto_all marker
280 src_blocks[0] = self.re_auto_all.sub('',src_blocks[0])
281 src_blocks[0] = self.re_auto_all.sub('',src_blocks[0])
281
282
282 self.nblocks = len(src_blocks)
283 self.nblocks = len(src_blocks)
283 self.src_blocks = src_blocks
284 self.src_blocks = src_blocks
284
285
285 # also build syntax-highlighted source
286 # also build syntax-highlighted source
286 self.src_blocks_colored = map(self.ip_colorize,self.src_blocks)
287 self.src_blocks_colored = map(self.ip_colorize,self.src_blocks)
287
288
288 # ensure clean namespace and seek offset
289 # ensure clean namespace and seek offset
289 self.reset()
290 self.reset()
290
291
291 def reset(self):
292 def reset(self):
292 """Reset the namespace and seek pointer to restart the demo"""
293 """Reset the namespace and seek pointer to restart the demo"""
293 self.user_ns = {}
294 self.user_ns = {}
294 self.finished = False
295 self.finished = False
295 self.block_index = 0
296 self.block_index = 0
296
297
297 def _validate_index(self,index):
298 def _validate_index(self,index):
298 if index<0 or index>=self.nblocks:
299 if index<0 or index>=self.nblocks:
299 raise ValueError('invalid block index %s' % index)
300 raise ValueError('invalid block index %s' % index)
300
301
301 def _get_index(self,index):
302 def _get_index(self,index):
302 """Get the current block index, validating and checking status.
303 """Get the current block index, validating and checking status.
303
304
304 Returns None if the demo is finished"""
305 Returns None if the demo is finished"""
305
306
306 if index is None:
307 if index is None:
307 if self.finished:
308 if self.finished:
308 print >>Term.cout, 'Demo finished. Use <demo_name>.reset() if you want to rerun it.'
309 print >>Term.cout, 'Demo finished. Use <demo_name>.reset() if you want to rerun it.'
309 return None
310 return None
310 index = self.block_index
311 index = self.block_index
311 else:
312 else:
312 self._validate_index(index)
313 self._validate_index(index)
313 return index
314 return index
314
315
315 def seek(self,index):
316 def seek(self,index):
316 """Move the current seek pointer to the given block.
317 """Move the current seek pointer to the given block.
317
318
318 You can use negative indices to seek from the end, with identical
319 You can use negative indices to seek from the end, with identical
319 semantics to those of Python lists."""
320 semantics to those of Python lists."""
320 if index<0:
321 if index<0:
321 index = self.nblocks + index
322 index = self.nblocks + index
322 self._validate_index(index)
323 self._validate_index(index)
323 self.block_index = index
324 self.block_index = index
324 self.finished = False
325 self.finished = False
325
326
326 def back(self,num=1):
327 def back(self,num=1):
327 """Move the seek pointer back num blocks (default is 1)."""
328 """Move the seek pointer back num blocks (default is 1)."""
328 self.seek(self.block_index-num)
329 self.seek(self.block_index-num)
329
330
330 def jump(self,num=1):
331 def jump(self,num=1):
331 """Jump a given number of blocks relative to the current one.
332 """Jump a given number of blocks relative to the current one.
332
333
333 The offset can be positive or negative, defaults to 1."""
334 The offset can be positive or negative, defaults to 1."""
334 self.seek(self.block_index+num)
335 self.seek(self.block_index+num)
335
336
336 def again(self):
337 def again(self):
337 """Move the seek pointer back one block and re-execute."""
338 """Move the seek pointer back one block and re-execute."""
338 self.back(1)
339 self.back(1)
339 self()
340 self()
340
341
341 def edit(self,index=None):
342 def edit(self,index=None):
342 """Edit a block.
343 """Edit a block.
343
344
344 If no number is given, use the last block executed.
345 If no number is given, use the last block executed.
345
346
346 This edits the in-memory copy of the demo, it does NOT modify the
347 This edits the in-memory copy of the demo, it does NOT modify the
347 original source file. If you want to do that, simply open the file in
348 original source file. If you want to do that, simply open the file in
348 an editor and use reload() when you make changes to the file. This
349 an editor and use reload() when you make changes to the file. This
349 method is meant to let you change a block during a demonstration for
350 method is meant to let you change a block during a demonstration for
350 explanatory purposes, without damaging your original script."""
351 explanatory purposes, without damaging your original script."""
351
352
352 index = self._get_index(index)
353 index = self._get_index(index)
353 if index is None:
354 if index is None:
354 return
355 return
355 # decrease the index by one (unless we're at the very beginning), so
356 # decrease the index by one (unless we're at the very beginning), so
356 # that the default demo.edit() call opens up the sblock we've last run
357 # that the default demo.edit() call opens up the sblock we've last run
357 if index>0:
358 if index>0:
358 index -= 1
359 index -= 1
359
360
360 filename = self.shell.mktempfile(self.src_blocks[index])
361 filename = self.shell.mktempfile(self.src_blocks[index])
361 self.shell.hooks.editor(filename,1)
362 self.shell.hooks.editor(filename,1)
362 new_block = file_read(filename)
363 new_block = file_read(filename)
363 # update the source and colored block
364 # update the source and colored block
364 self.src_blocks[index] = new_block
365 self.src_blocks[index] = new_block
365 self.src_blocks_colored[index] = self.ip_colorize(new_block)
366 self.src_blocks_colored[index] = self.ip_colorize(new_block)
366 self.block_index = index
367 self.block_index = index
367 # call to run with the newly edited index
368 # call to run with the newly edited index
368 self()
369 self()
369
370
370 def show(self,index=None):
371 def show(self,index=None):
371 """Show a single block on screen"""
372 """Show a single block on screen"""
372
373
373 index = self._get_index(index)
374 index = self._get_index(index)
374 if index is None:
375 if index is None:
375 return
376 return
376
377
377 print >>Term.cout, self.marquee('<%s> block # %s (%s remaining)' %
378 print >>Term.cout, self.marquee('<%s> block # %s (%s remaining)' %
378 (self.title,index,self.nblocks-index-1))
379 (self.title,index,self.nblocks-index-1))
379 print >>Term.cout,(self.src_blocks_colored[index])
380 print >>Term.cout,(self.src_blocks_colored[index])
380 sys.stdout.flush()
381 sys.stdout.flush()
381
382
382 def show_all(self):
383 def show_all(self):
383 """Show entire demo on screen, block by block"""
384 """Show entire demo on screen, block by block"""
384
385
385 fname = self.title
386 fname = self.title
386 title = self.title
387 title = self.title
387 nblocks = self.nblocks
388 nblocks = self.nblocks
388 silent = self._silent
389 silent = self._silent
389 marquee = self.marquee
390 marquee = self.marquee
390 for index,block in enumerate(self.src_blocks_colored):
391 for index,block in enumerate(self.src_blocks_colored):
391 if silent[index]:
392 if silent[index]:
392 print >>Term.cout, marquee('<%s> SILENT block # %s (%s remaining)' %
393 print >>Term.cout, marquee('<%s> SILENT block # %s (%s remaining)' %
393 (title,index,nblocks-index-1))
394 (title,index,nblocks-index-1))
394 else:
395 else:
395 print >>Term.cout, marquee('<%s> block # %s (%s remaining)' %
396 print >>Term.cout, marquee('<%s> block # %s (%s remaining)' %
396 (title,index,nblocks-index-1))
397 (title,index,nblocks-index-1))
397 print >>Term.cout, block,
398 print >>Term.cout, block,
398 sys.stdout.flush()
399 sys.stdout.flush()
399
400
400 def runlines(self,source):
401 def runlines(self,source):
401 """Execute a string with one or more lines of code"""
402 """Execute a string with one or more lines of code"""
402
403
403 exec source in self.user_ns
404 exec source in self.user_ns
404
405
405 def __call__(self,index=None):
406 def __call__(self,index=None):
406 """run a block of the demo.
407 """run a block of the demo.
407
408
408 If index is given, it should be an integer >=1 and <= nblocks. This
409 If index is given, it should be an integer >=1 and <= nblocks. This
409 means that the calling convention is one off from typical Python
410 means that the calling convention is one off from typical Python
410 lists. The reason for the inconsistency is that the demo always
411 lists. The reason for the inconsistency is that the demo always
411 prints 'Block n/N, and N is the total, so it would be very odd to use
412 prints 'Block n/N, and N is the total, so it would be very odd to use
412 zero-indexing here."""
413 zero-indexing here."""
413
414
414 index = self._get_index(index)
415 index = self._get_index(index)
415 if index is None:
416 if index is None:
416 return
417 return
417 try:
418 try:
418 marquee = self.marquee
419 marquee = self.marquee
419 next_block = self.src_blocks[index]
420 next_block = self.src_blocks[index]
420 self.block_index += 1
421 self.block_index += 1
421 if self._silent[index]:
422 if self._silent[index]:
422 print >>Term.cout, marquee('Executing silent block # %s (%s remaining)' %
423 print >>Term.cout, marquee('Executing silent block # %s (%s remaining)' %
423 (index,self.nblocks-index-1))
424 (index,self.nblocks-index-1))
424 else:
425 else:
425 self.pre_cmd()
426 self.pre_cmd()
426 self.show(index)
427 self.show(index)
427 if self.auto_all or self._auto[index]:
428 if self.auto_all or self._auto[index]:
428 print >>Term.cout, marquee('output:')
429 print >>Term.cout, marquee('output:')
429 else:
430 else:
430 print >>Term.cout, marquee('Press <q> to quit, <Enter> to execute...'),
431 print >>Term.cout, marquee('Press <q> to quit, <Enter> to execute...'),
431 ans = raw_input().strip()
432 ans = raw_input().strip()
432 if ans:
433 if ans:
433 print >>Term.cout, marquee('Block NOT executed')
434 print >>Term.cout, marquee('Block NOT executed')
434 return
435 return
435 try:
436 try:
436 save_argv = sys.argv
437 save_argv = sys.argv
437 sys.argv = self.sys_argv
438 sys.argv = self.sys_argv
438 self.runlines(next_block)
439 self.runlines(next_block)
439 self.post_cmd()
440 self.post_cmd()
440 finally:
441 finally:
441 sys.argv = save_argv
442 sys.argv = save_argv
442
443
443 except:
444 except:
444 self.ip_showtb(filename=self.fname)
445 self.ip_showtb(filename=self.fname)
445 else:
446 else:
446 self.ip_ns.update(self.user_ns)
447 self.ip_ns.update(self.user_ns)
447
448
448 if self.block_index == self.nblocks:
449 if self.block_index == self.nblocks:
449 mq1 = self.marquee('END OF DEMO')
450 mq1 = self.marquee('END OF DEMO')
450 if mq1:
451 if mq1:
451 # avoid spurious print >>Term.cout,s if empty marquees are used
452 # avoid spurious print >>Term.cout,s if empty marquees are used
452 print >>Term.cout
453 print >>Term.cout
453 print >>Term.cout, mq1
454 print >>Term.cout, mq1
454 print >>Term.cout, self.marquee('Use <demo_name>.reset() if you want to rerun it.')
455 print >>Term.cout, self.marquee('Use <demo_name>.reset() if you want to rerun it.')
455 self.finished = True
456 self.finished = True
456
457
457 # These methods are meant to be overridden by subclasses who may wish to
458 # These methods are meant to be overridden by subclasses who may wish to
458 # customize the behavior of of their demos.
459 # customize the behavior of of their demos.
459 def marquee(self,txt='',width=78,mark='*'):
460 def marquee(self,txt='',width=78,mark='*'):
460 """Return the input string centered in a 'marquee'."""
461 """Return the input string centered in a 'marquee'."""
461 return marquee(txt,width,mark)
462 return marquee(txt,width,mark)
462
463
463 def pre_cmd(self):
464 def pre_cmd(self):
464 """Method called before executing each block."""
465 """Method called before executing each block."""
465 pass
466 pass
466
467
467 def post_cmd(self):
468 def post_cmd(self):
468 """Method called after executing each block."""
469 """Method called after executing each block."""
469 pass
470 pass
470
471
471
472
472 class IPythonDemo(Demo):
473 class IPythonDemo(Demo):
473 """Class for interactive demos with IPython's input processing applied.
474 """Class for interactive demos with IPython's input processing applied.
474
475
475 This subclasses Demo, but instead of executing each block by the Python
476 This subclasses Demo, but instead of executing each block by the Python
476 interpreter (via exec), it actually calls IPython on it, so that any input
477 interpreter (via exec), it actually calls IPython on it, so that any input
477 filters which may be in place are applied to the input block.
478 filters which may be in place are applied to the input block.
478
479
479 If you have an interactive environment which exposes special input
480 If you have an interactive environment which exposes special input
480 processing, you can use this class instead to write demo scripts which
481 processing, you can use this class instead to write demo scripts which
481 operate exactly as if you had typed them interactively. The default Demo
482 operate exactly as if you had typed them interactively. The default Demo
482 class requires the input to be valid, pure Python code.
483 class requires the input to be valid, pure Python code.
483 """
484 """
484
485
485 def runlines(self,source):
486 def runlines(self,source):
486 """Execute a string with one or more lines of code"""
487 """Execute a string with one or more lines of code"""
487
488
488 self.shell.runlines(source)
489 self.shell.runlines(source)
489
490
490 class LineDemo(Demo):
491 class LineDemo(Demo):
491 """Demo where each line is executed as a separate block.
492 """Demo where each line is executed as a separate block.
492
493
493 The input script should be valid Python code.
494 The input script should be valid Python code.
494
495
495 This class doesn't require any markup at all, and it's meant for simple
496 This class doesn't require any markup at all, and it's meant for simple
496 scripts (with no nesting or any kind of indentation) which consist of
497 scripts (with no nesting or any kind of indentation) which consist of
497 multiple lines of input to be executed, one at a time, as if they had been
498 multiple lines of input to be executed, one at a time, as if they had been
498 typed in the interactive prompt."""
499 typed in the interactive prompt."""
499
500
500 def reload(self):
501 def reload(self):
501 """Reload source from disk and initialize state."""
502 """Reload source from disk and initialize state."""
502 # read data and parse into blocks
503 # read data and parse into blocks
503 src_b = [l for l in self.fobj.readline() if l.strip()]
504 src_b = [l for l in self.fobj.readline() if l.strip()]
504 nblocks = len(src_b)
505 nblocks = len(src_b)
505 self.src = os.linesep.join(self.fobj.readlines())
506 self.src = os.linesep.join(self.fobj.readlines())
506 self._silent = [False]*nblocks
507 self._silent = [False]*nblocks
507 self._auto = [True]*nblocks
508 self._auto = [True]*nblocks
508 self.auto_all = True
509 self.auto_all = True
509 self.nblocks = nblocks
510 self.nblocks = nblocks
510 self.src_blocks = src_b
511 self.src_blocks = src_b
511
512
512 # also build syntax-highlighted source
513 # also build syntax-highlighted source
513 self.src_blocks_colored = map(self.ip_colorize,self.src_blocks)
514 self.src_blocks_colored = map(self.ip_colorize,self.src_blocks)
514
515
515 # ensure clean namespace and seek offset
516 # ensure clean namespace and seek offset
516 self.reset()
517 self.reset()
517
518
518
519
519 class IPythonLineDemo(IPythonDemo,LineDemo):
520 class IPythonLineDemo(IPythonDemo,LineDemo):
520 """Variant of the LineDemo class whose input is processed by IPython."""
521 """Variant of the LineDemo class whose input is processed by IPython."""
521 pass
522 pass
522
523
523
524
524 class ClearMixin(object):
525 class ClearMixin(object):
525 """Use this mixin to make Demo classes with less visual clutter.
526 """Use this mixin to make Demo classes with less visual clutter.
526
527
527 Demos using this mixin will clear the screen before every block and use
528 Demos using this mixin will clear the screen before every block and use
528 blank marquees.
529 blank marquees.
529
530
530 Note that in order for the methods defined here to actually override those
531 Note that in order for the methods defined here to actually override those
531 of the classes it's mixed with, it must go /first/ in the inheritance
532 of the classes it's mixed with, it must go /first/ in the inheritance
532 tree. For example:
533 tree. For example:
533
534
534 class ClearIPDemo(ClearMixin,IPythonDemo): pass
535 class ClearIPDemo(ClearMixin,IPythonDemo): pass
535
536
536 will provide an IPythonDemo class with the mixin's features.
537 will provide an IPythonDemo class with the mixin's features.
537 """
538 """
538
539
539 def marquee(self,txt='',width=78,mark='*'):
540 def marquee(self,txt='',width=78,mark='*'):
540 """Blank marquee that returns '' no matter what the input."""
541 """Blank marquee that returns '' no matter what the input."""
541 return ''
542 return ''
542
543
543 def pre_cmd(self):
544 def pre_cmd(self):
544 """Method called before executing each block.
545 """Method called before executing each block.
545
546
546 This one simply clears the screen."""
547 This one simply clears the screen."""
547 from IPython.utils.terminal import term_clear
548 from IPython.utils.terminal import term_clear
548 term_clear()
549 term_clear()
549
550
550 class ClearDemo(ClearMixin,Demo):
551 class ClearDemo(ClearMixin,Demo):
551 pass
552 pass
552
553
553
554
554 class ClearIPDemo(ClearMixin,IPythonDemo):
555 class ClearIPDemo(ClearMixin,IPythonDemo):
555 pass
556 pass
General Comments 0
You need to be logged in to leave comments. Login now