##// END OF EJS Templates
Demo fixes, see changelog
fperez -
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,115 +1,149 b''
1 1 """Module for interactive demos using IPython.
2
3 Sorry, but this uses Python 2.3 features, so it won't work in 2.2 environments.
2 4 """
3 5 #*****************************************************************************
4 6 # Copyright (C) 2005 Fernando Perez. <Fernando.Perez@colorado.edu>
5 7 #
6 8 # Distributed under the terms of the BSD License. The full license is in
7 9 # the file COPYING, distributed as part of this software.
8 10 #
9 11 #*****************************************************************************
10 12
11 13 import exceptions
14 import re
12 15
13 16 from IPython.PyColorize import Parser
14 17 from IPython.genutils import marquee
15 18
16 19 class DemoError(exceptions.Exception): pass
17 20
18 21 class Demo:
19 def __init__(self,fname,pause_mark='# pause',auto=False):
22 def __init__(self,fname,mark_pause='# pause',mark_silent='# silent',
23 auto=False):
24 """The marks are turned into regexps which match them as standalone in
25 a line, with all leading/trailing whitespace ignored."""
20 26
21 27 self.fname = fname
22 self.pause_mark = pause_mark
28 self.mark_pause = mark_pause
29 self.re_pause = re.compile(r'^\s*%s\s*$' % mark_pause,re.MULTILINE)
30 self.mark_silent = mark_silent
31 self.re_silent = re.compile(r'^\s*%s\s*$' % mark_silent,re.MULTILINE)
23 32 self.auto = auto
24 33
25 34 # get a few things from ipython. While it's a bit ugly design-wise,
26 35 # it ensures that things like color scheme and the like are always in
27 36 # sync with the ipython mode being used. This class is only meant to
28 37 # be used inside ipython anyways, so it's OK.
29 38 self.ip_showtraceback = __IPYTHON__.showtraceback
30 39 self.ip_ns = __IPYTHON__.user_ns
31 40 self.ip_colors = __IPYTHON__.rc['colors']
32 41
33 42 # read data and parse into blocks
34 43 fobj = file(fname,'r')
35 44 self.src = fobj.read()
36 45 fobj.close()
37 self.src_blocks = [b.strip() for b in self.src.split(pause_mark) if b]
46 self.src_blocks = [b.strip() for b in self.re_pause.split(self.src) if b]
47 self.silent = [bool(self.re_silent.findall(b)) for b in self.src_blocks]
38 48 self.nblocks = len(self.src_blocks)
39 49
40 50 # try to colorize blocks
41 51 colorize = Parser().format
42 52 col_scheme = self.ip_colors
43 53 self.src_blocks_colored = [colorize(s_blk,'str',col_scheme)
44 54 for s_blk in self.src_blocks]
45 55
46 56 # finish initialization
47 57 self.reset()
48 58
49 59 def reset(self):
60 """Reset the namespace and seek pointer to restart the demo"""
50 61 self.user_ns = {}
51 62 self.finished = False
52 63 self.block_index = 0
53 64
54 65 def again(self):
66 """Repeat the last block"""
55 67 self.block_index -= 1
56 68 self()
57 69
58
59 70 def _validate_index(self,index):
60 71 if index<0 or index>=self.nblocks:
61 72 raise ValueError('invalid block index %s' % index)
62 73
63 74 def seek(self,index):
75 """Move the current seek pointer to the given block"""
64 76 self._validate_index(index)
65 77 self.block_index = index-1
66 78 self.finished = False
67 79
68 def show(self,index=None):
80 def show_block(self,index=None):
81 """Show a single block on screen"""
69 82 if index is None:
83 if self.finished:
84 print 'Demo finished. Use reset() if you want to rerun it.'
85 return
70 86 index = self.block_index
71 87 else:
72 88 self._validate_index(index)
73 89 print marquee('<%s> block # %s (%s/%s)' %
74 90 (self.fname,index,index+1,self.nblocks))
75 91 print self.src_blocks_colored[index],
76
92
93 def show(self):
94 """Show entire demo on screen, block by block"""
95
96 fname = self.fname
97 nblocks = self.nblocks
98 silent = self.silent
99 for index,block in enumerate(self.src_blocks_colored):
100 if silent[index]:
101 print marquee('<%s> SILENT block # %s (%s/%s)' %
102 (fname,index,index+1,nblocks))
103 else:
104 print marquee('<%s> block # %s (%s/%s)' %
105 (fname,index,index+1,nblocks))
106 print block,
107
77 108 def __call__(self,index=None):
78 109 """run a block of the demo.
79 110
80 111 If index is given, it should be an integer >=1 and <= nblocks. This
81 112 means that the calling convention is one off from typical Python
82 113 lists. The reason for the inconsistency is that the demo always
83 114 prints 'Block n/N, and N is the total, so it would be very odd to use
84 115 zero-indexing here."""
85 116
86 117 if index is None and self.finished:
87 118 print 'Demo finished. Use reset() if you want to rerun it.'
88 119 return
89 120 if index is None:
90 121 index = self.block_index
91 122 self._validate_index(index)
92 123 try:
93 124 next_block = self.src_blocks[index]
94 125 self.block_index += 1
95 self.show(index)
96 if not self.auto:
97 print marquee('Press <q> to quit, <Enter> to execute...'),
98 ans = raw_input().strip()
99 if ans:
100 print marquee('Block NOT executed')
101 return
126 if self.silent[index]:
127 print marquee('Executing silent block # %s (%s/%s)' %
128 (index,index+1,self.nblocks))
129 else:
130 self.show_block(index)
131 if not self.auto:
132 print marquee('Press <q> to quit, <Enter> to execute...'),
133 ans = raw_input().strip()
134 if ans:
135 print marquee('Block NOT executed')
136 return
102 137
103 138 exec next_block in self.user_ns
104 139
105 140 except:
106 141 self.ip_showtraceback(filename=self.fname)
107 142 else:
108 143 self.ip_ns.update(self.user_ns)
109 144
110 145 if self.block_index == self.nblocks:
111 146 print
112 147 print marquee(' END OF DEMO ')
113 148 print marquee('Use reset() if you want to rerun it.')
114 149 self.finished = True
115
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now