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