##// END OF EJS Templates
fix again() bug in demo
fperez -
Show More

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

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