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