##// END OF EJS Templates
- Bug fixes in Demo code to support demos with IPython syntax...
fperez -
Show More
@@ -1,7 +1,7 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Magic functions for InteractiveShell.
2 """Magic functions for InteractiveShell.
3
3
4 $Id: Magic.py 1981 2006-12-12 21:51:54Z vivainio $"""
4 $Id: Magic.py 2036 2007-01-27 07:30:22Z fperez $"""
5
5
6 #*****************************************************************************
6 #*****************************************************************************
7 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
7 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
@@ -2617,16 +2617,20 b' Defaulting color scheme to \'NoColor\'"""'
2617 if ps:
2617 if ps:
2618 try:
2618 try:
2619 os.chdir(os.path.expanduser(ps))
2619 os.chdir(os.path.expanduser(ps))
2620 ttitle = ("IPy:" + (
2620 if self.shell.rc.term_title:
2621 os.getcwd() == '/' and '/' or os.path.basename(os.getcwd())))
2621 #print 'set term title:',self.shell.rc.term_title # dbg
2622 platutils.set_term_title(ttitle)
2622 ttitle = ("IPy:" + (
2623 os.getcwd() == '/' and '/' or \
2624 os.path.basename(os.getcwd())))
2625 platutils.set_term_title(ttitle)
2623 except OSError:
2626 except OSError:
2624 print sys.exc_info()[1]
2627 print sys.exc_info()[1]
2625 else:
2628 else:
2626 self.shell.user_ns['_dh'].append(os.getcwd())
2629 self.shell.user_ns['_dh'].append(os.getcwd())
2627 else:
2630 else:
2628 os.chdir(self.shell.home_dir)
2631 os.chdir(self.shell.home_dir)
2629 platutils.set_term_title("IPy:~")
2632 if self.shell.rc.term_title:
2633 platutils.set_term_title("IPy:~")
2630 self.shell.user_ns['_dh'].append(os.getcwd())
2634 self.shell.user_ns['_dh'].append(os.getcwd())
2631 if not 'q' in opts:
2635 if not 'q' in opts:
2632 print self.shell.user_ns['_dh'][-1]
2636 print self.shell.user_ns['_dh'][-1]
@@ -5,6 +5,10 b' 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
9 Provided classes
10 ================
11
8 The classes are (see their docstrings for further details):
12 The classes are (see their docstrings for further details):
9
13
10 - Demo: pure python demos
14 - Demo: pure python demos
@@ -20,6 +24,24 b' The classes are (see their docstrings for further details):'
20 executed a line at a time, but processed via IPython).
24 executed a line at a time, but processed via IPython).
21
25
22
26
27 Subclassing
28 ===========
29
30 The classes here all include a few methods meant to make customization by
31 subclassing more convenient. Their docstrings below have some more details:
32
33 - marquee(): generates a marquee to provide visible on-screen markers at each
34 block start and end.
35
36 - pre_cmd(): run right before the execution of each block.
37
38 - pre_cmd(): run right after the execution of each block. If the block
39 raises an exception, this is NOT called.
40
41
42 Operation
43 =========
44
23 The file is run in its own empty namespace (though you can pass it a string of
45 The file is run in its own empty namespace (though you can pass it a string of
24 arguments as if in a command line environment, and it will see those as
46 arguments as if in a command line environment, and it will see those as
25 sys.argv). But at each stop, the global IPython namespace is updated with the
47 sys.argv). But at each stop, the global IPython namespace is updated with the
@@ -76,6 +98,12 b' has a few useful methods for navigation, like again(), edit(), jump(), seek()'
76 and back(). It can be reset for a new run via reset() or reloaded from disk
98 and back(). It can be reset for a new run via reset() or reloaded from disk
77 (in case you've edited the source) via reload(). See their docstrings below.
99 (in case you've edited the source) via reload(). See their docstrings below.
78
100
101
102 Example
103 =======
104
105 The following is a very simple example of a valid demo file.
106
79 #################### EXAMPLE DEMO <ex_demo.py> ###############################
107 #################### EXAMPLE DEMO <ex_demo.py> ###############################
80 '''A simple interactive demo to illustrate the use of IPython's Demo class.'''
108 '''A simple interactive demo to illustrate the use of IPython's Demo class.'''
81
109
@@ -111,6 +139,7 b" print 'z is now:', z"
111 print 'bye!'
139 print 'bye!'
112 ################### END EXAMPLE DEMO <ex_demo.py> ############################
140 ################### END EXAMPLE DEMO <ex_demo.py> ############################
113 """
141 """
142
114 #*****************************************************************************
143 #*****************************************************************************
115 # Copyright (C) 2005-2006 Fernando Perez. <Fernando.Perez@colorado.edu>
144 # Copyright (C) 2005-2006 Fernando Perez. <Fernando.Perez@colorado.edu>
116 #
145 #
@@ -296,8 +325,8 b' class Demo:'
296 if index is None:
325 if index is None:
297 return
326 return
298
327
299 print marquee('<%s> block # %s (%s remaining)' %
328 print self.marquee('<%s> block # %s (%s remaining)' %
300 (self.fname,index,self.nblocks-index-1))
329 (self.fname,index,self.nblocks-index-1))
301 print self.src_blocks_colored[index],
330 print self.src_blocks_colored[index],
302 sys.stdout.flush()
331 sys.stdout.flush()
303
332
@@ -307,6 +336,7 b' class Demo:'
307 fname = self.fname
336 fname = self.fname
308 nblocks = self.nblocks
337 nblocks = self.nblocks
309 silent = self._silent
338 silent = self._silent
339 marquee = self.marquee
310 for index,block in enumerate(self.src_blocks_colored):
340 for index,block in enumerate(self.src_blocks_colored):
311 if silent[index]:
341 if silent[index]:
312 print marquee('<%s> SILENT block # %s (%s remaining)' %
342 print marquee('<%s> SILENT block # %s (%s remaining)' %
@@ -335,6 +365,7 b' class Demo:'
335 if index is None:
365 if index is None:
336 return
366 return
337 try:
367 try:
368 marquee = self.marquee
338 next_block = self.src_blocks[index]
369 next_block = self.src_blocks[index]
339 self.block_index += 1
370 self.block_index += 1
340 if self._silent[index]:
371 if self._silent[index]:
@@ -353,7 +384,9 b' class Demo:'
353 try:
384 try:
354 save_argv = sys.argv
385 save_argv = sys.argv
355 sys.argv = self.sys_argv
386 sys.argv = self.sys_argv
387 self.pre_cmd()
356 self.runlines(next_block)
388 self.runlines(next_block)
389 self.post_cmd()
357 finally:
390 finally:
358 sys.argv = save_argv
391 sys.argv = save_argv
359
392
@@ -364,10 +397,25 b' class Demo:'
364
397
365 if self.block_index == self.nblocks:
398 if self.block_index == self.nblocks:
366 print
399 print
367 print marquee(' END OF DEMO ')
400 print self.marquee(' END OF DEMO ')
368 print marquee('Use reset() if you want to rerun it.')
401 print self.marquee('Use reset() if you want to rerun it.')
369 self.finished = True
402 self.finished = True
370
403
404 # These methods are meant to be overridden by subclasses who may wish to
405 # customize the behavior of of their demos.
406 def marquee(self,txt='',width=78,mark='*'):
407 """Return the input string centered in a 'marquee'."""
408 return marquee(txt,width,mark)
409
410 def pre_cmd(self):
411 """Method called before executing each block."""
412 pass
413
414 def post_cmd(self):
415 """Method called after executing each block."""
416 pass
417
418
371 class IPythonDemo(Demo):
419 class IPythonDemo(Demo):
372 """Class for interactive demos with IPython's input processing applied.
420 """Class for interactive demos with IPython's input processing applied.
373
421
@@ -384,7 +432,7 b' class IPythonDemo(Demo):'
384 def runlines(self,source):
432 def runlines(self,source):
385 """Execute a string with one or more lines of code"""
433 """Execute a string with one or more lines of code"""
386
434
387 self.runlines(source)
435 self.shell.runlines(source)
388
436
389 class LineDemo(Demo):
437 class LineDemo(Demo):
390 """Demo where each line is executed as a separate block.
438 """Demo where each line is executed as a separate block.
@@ -6,7 +6,7 b' Requires Python 2.1 or better.'
6
6
7 This file contains the main make_IPython() starter function.
7 This file contains the main make_IPython() starter function.
8
8
9 $Id: ipmaker.py 2029 2007-01-22 06:35:15Z fperez $"""
9 $Id: ipmaker.py 2036 2007-01-27 07:30:22Z fperez $"""
10
10
11 #*****************************************************************************
11 #*****************************************************************************
12 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
12 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
@@ -162,7 +162,7 b" object? -> Details about 'object'. ?object also works, ?? prints more."
162 'separate_out2|so2=s xmode=s wildcards_case_sensitive! '
162 'separate_out2|so2=s xmode=s wildcards_case_sensitive! '
163 'magic_docstrings system_verbose! '
163 'magic_docstrings system_verbose! '
164 'multi_line_specials! '
164 'multi_line_specials! '
165 'wxversion=s '
165 'term_title! wxversion=s '
166 'autoedit_syntax!')
166 'autoedit_syntax!')
167
167
168 # Options that can *only* appear at the cmd line (not in rcfiles).
168 # Options that can *only* appear at the cmd line (not in rcfiles).
@@ -225,6 +225,7 b" object? -> Details about 'object'. ?object also works, ?? prints more."
225 q4thread = 0,
225 q4thread = 0,
226 wthread = 0,
226 wthread = 0,
227 pylab = 0,
227 pylab = 0,
228 term_title = 1,
228 tk = 0,
229 tk = 0,
229 upgrade = 0,
230 upgrade = 0,
230 Version = 0,
231 Version = 0,
@@ -49,7 +49,7 b' runner [opts] script_name'
49 class InteractiveRunner(object):
49 class InteractiveRunner(object):
50 """Class to run a sequence of commands through an interactive program."""
50 """Class to run a sequence of commands through an interactive program."""
51
51
52 def __init__(self,program,prompts,args=None):
52 def __init__(self,program,prompts,args=None,out=sys.stdout,echo=True):
53 """Construct a runner.
53 """Construct a runner.
54
54
55 Inputs:
55 Inputs:
@@ -73,6 +73,9 b' class InteractiveRunner(object):'
73 - args(None): optional list of strings to pass as arguments to the
73 - args(None): optional list of strings to pass as arguments to the
74 child program.
74 child program.
75
75
76 - out(sys.stdout): if given, an output stream to be used when writing
77 output. The only requirement is that it must have a .write() method.
78
76 Public members not parameterized in the constructor:
79 Public members not parameterized in the constructor:
77
80
78 - delaybeforesend(0): Newer versions of pexpect have a delay before
81 - delaybeforesend(0): Newer versions of pexpect have a delay before
@@ -87,11 +90,30 b' class InteractiveRunner(object):'
87 self.prompts = prompts
90 self.prompts = prompts
88 if args is None: args = []
91 if args is None: args = []
89 self.args = args
92 self.args = args
93 self.out = out
94 self.echo = echo
90 # Other public members which we don't make as parameters, but which
95 # Other public members which we don't make as parameters, but which
91 # users may occasionally want to tweak
96 # users may occasionally want to tweak
92 self.delaybeforesend = 0
97 self.delaybeforesend = 0
93
98
94 def run_file(self,fname,interact=False):
99 # Create child process and hold on to it so we don't have to re-create
100 # for every single execution call
101 c = self.child = pexpect.spawn(self.program,self.args,timeout=None)
102 c.delaybeforesend = self.delaybeforesend
103 # pexpect hard-codes the terminal size as (24,80) (rows,columns).
104 # This causes problems because any line longer than 80 characters gets
105 # completely overwrapped on the printed outptut (even though
106 # internally the code runs fine). We reset this to 99 rows X 200
107 # columns (arbitrarily chosen), which should avoid problems in all
108 # reasonable cases.
109 c.setwinsize(99,200)
110
111 def close(self):
112 """close child process"""
113
114 self.child.close()
115
116 def run_file(self,fname,interact=False,get_output=False):
95 """Run the given file interactively.
117 """Run the given file interactively.
96
118
97 Inputs:
119 Inputs:
@@ -103,11 +125,13 b' class InteractiveRunner(object):'
103
125
104 fobj = open(fname,'r')
126 fobj = open(fname,'r')
105 try:
127 try:
106 self.run_source(fobj,interact)
128 out = self.run_source(fobj,interact,get_output)
107 finally:
129 finally:
108 fobj.close()
130 fobj.close()
131 if get_output:
132 return out
109
133
110 def run_source(self,source,interact=False):
134 def run_source(self,source,interact=False,get_output=False):
111 """Run the given source code interactively.
135 """Run the given source code interactively.
112
136
113 Inputs:
137 Inputs:
@@ -119,6 +143,12 b' class InteractiveRunner(object):'
119
143
120 - interact(False): if true, start to interact with the running
144 - interact(False): if true, start to interact with the running
121 program at the end of the script. Otherwise, just exit.
145 program at the end of the script. Otherwise, just exit.
146
147 - get_output(False): if true, capture the output of the child process
148 (filtering the input commands out) and return it as a string.
149
150 Returns:
151 A string containing the process output, but only if requested.
122 """
152 """
123
153
124 # if the source is a string, chop it up in lines so we can iterate
154 # if the source is a string, chop it up in lines so we can iterate
@@ -126,39 +156,38 b' class InteractiveRunner(object):'
126 if not isinstance(source,file):
156 if not isinstance(source,file):
127 source = source.splitlines(True)
157 source = source.splitlines(True)
128
158
129 # grab the true write method of stdout, in case anything later
159 if self.echo:
130 # reassigns sys.stdout, so that we really are writing to the true
160 # normalize all strings we write to use the native OS line
131 # stdout and not to something else. We also normalize all strings we
161 # separators.
132 # write to use the native OS line separators.
162 linesep = os.linesep
133 linesep = os.linesep
163 stdwrite = self.out.write
134 stdwrite = sys.stdout.write
164 write = lambda s: stdwrite(s.replace('\r\n',linesep))
135 write = lambda s: stdwrite(s.replace('\r\n',linesep))
165 else:
136
166 # Quiet mode, all writes are no-ops
137 c = pexpect.spawn(self.program,self.args,timeout=None)
167 write = lambda s: None
138 c.delaybeforesend = self.delaybeforesend
139
140 # pexpect hard-codes the terminal size as (24,80) (rows,columns).
141 # This causes problems because any line longer than 80 characters gets
142 # completely overwrapped on the printed outptut (even though
143 # internally the code runs fine). We reset this to 99 rows X 200
144 # columns (arbitrarily chosen), which should avoid problems in all
145 # reasonable cases.
146 c.setwinsize(99,200)
147
168
169 c = self.child
148 prompts = c.compile_pattern_list(self.prompts)
170 prompts = c.compile_pattern_list(self.prompts)
149
150 prompt_idx = c.expect_list(prompts)
171 prompt_idx = c.expect_list(prompts)
172
151 # Flag whether the script ends normally or not, to know whether we can
173 # Flag whether the script ends normally or not, to know whether we can
152 # do anything further with the underlying process.
174 # do anything further with the underlying process.
153 end_normal = True
175 end_normal = True
176
177 # If the output was requested, store it in a list for return at the end
178 if get_output:
179 output = []
180 store_output = output.append
181
154 for cmd in source:
182 for cmd in source:
155 # skip blank lines for all matches to the 'main' prompt, while the
183 # skip blank lines for all matches to the 'main' prompt, while the
156 # secondary prompts do not
184 # secondary prompts do not
157 if prompt_idx==0 and \
185 if prompt_idx==0 and \
158 (cmd.isspace() or cmd.lstrip().startswith('#')):
186 (cmd.isspace() or cmd.lstrip().startswith('#')):
159 print cmd,
187 write(cmd)
160 continue
188 continue
161
189
190 #write('AFTER: '+c.after) # dbg
162 write(c.after)
191 write(c.after)
163 c.send(cmd)
192 c.send(cmd)
164 try:
193 try:
@@ -168,8 +197,17 b' class InteractiveRunner(object):'
168 write(c.before)
197 write(c.before)
169 end_normal = False
198 end_normal = False
170 break
199 break
200
171 write(c.before)
201 write(c.before)
172
202
203 # With an echoing process, the output we get in c.before contains
204 # the command sent, a newline, and then the actual process output
205 if get_output:
206 store_output(c.before[len(cmd+'\n'):])
207 #write('CMD: <<%s>>' % cmd) # dbg
208 #write('OUTPUT: <<%s>>' % output[-1]) # dbg
209
210 self.out.flush()
173 if end_normal:
211 if end_normal:
174 if interact:
212 if interact:
175 c.send('\n')
213 c.send('\n')
@@ -182,13 +220,19 b' class InteractiveRunner(object):'
182 # space is there to make sure it gets printed, otherwise
220 # space is there to make sure it gets printed, otherwise
183 # OS buffering sometimes just suppresses it.
221 # OS buffering sometimes just suppresses it.
184 write(' \n')
222 write(' \n')
185 sys.stdout.flush()
223 self.out.flush()
186 else:
187 c.close()
188 else:
224 else:
189 if interact:
225 if interact:
190 e="Further interaction is not possible: child process is dead."
226 e="Further interaction is not possible: child process is dead."
191 print >> sys.stderr, e
227 print >> sys.stderr, e
228
229 # Leave the child ready for more input later on, otherwise select just
230 # hangs on the second invocation.
231 c.send('\n')
232
233 # Return any requested output
234 if get_output:
235 return ''.join(output)
192
236
193 def main(self,argv=None):
237 def main(self,argv=None):
194 """Run as a command-line script."""
238 """Run as a command-line script."""
@@ -221,26 +265,28 b' class IPythonRunner(InteractiveRunner):'
221 prompts would break this.
265 prompts would break this.
222 """
266 """
223
267
224 def __init__(self,program = 'ipython',args=None):
268 def __init__(self,program = 'ipython',args=None,out=sys.stdout,echo=True):
225 """New runner, optionally passing the ipython command to use."""
269 """New runner, optionally passing the ipython command to use."""
226
270
227 args0 = ['-colors','NoColor',
271 args0 = ['-colors','NoColor',
228 '-pi1','In [\\#]: ',
272 '-pi1','In [\\#]: ',
229 '-pi2',' .\\D.: ']
273 '-pi2',' .\\D.: ',
274 '-noterm_title',
275 '-noautoindent']
230 if args is None: args = args0
276 if args is None: args = args0
231 else: args = args0 + args
277 else: args = args0 + args
232 prompts = [r'In \[\d+\]: ',r' \.*: ']
278 prompts = [r'In \[\d+\]: ',r' \.*: ']
233 InteractiveRunner.__init__(self,program,prompts,args)
279 InteractiveRunner.__init__(self,program,prompts,args,out,echo)
234
280
235
281
236 class PythonRunner(InteractiveRunner):
282 class PythonRunner(InteractiveRunner):
237 """Interactive Python runner."""
283 """Interactive Python runner."""
238
284
239 def __init__(self,program='python',args=None):
285 def __init__(self,program='python',args=None,out=sys.stdout,echo=True):
240 """New runner, optionally passing the python command to use."""
286 """New runner, optionally passing the python command to use."""
241
287
242 prompts = [r'>>> ',r'\.\.\. ']
288 prompts = [r'>>> ',r'\.\.\. ']
243 InteractiveRunner.__init__(self,program,prompts,args)
289 InteractiveRunner.__init__(self,program,prompts,args,out,echo)
244
290
245
291
246 class SAGERunner(InteractiveRunner):
292 class SAGERunner(InteractiveRunner):
@@ -250,11 +296,11 b' class SAGERunner(InteractiveRunner):'
250 to use 'colors NoColor' in the ipythonrc config file, since currently the
296 to use 'colors NoColor' in the ipythonrc config file, since currently the
251 prompt matching regexp does not identify color sequences."""
297 prompt matching regexp does not identify color sequences."""
252
298
253 def __init__(self,program='sage',args=None):
299 def __init__(self,program='sage',args=None,out=sys.stdout,echo=True):
254 """New runner, optionally passing the sage command to use."""
300 """New runner, optionally passing the sage command to use."""
255
301
256 prompts = ['sage: ',r'\s*\.\.\. ']
302 prompts = ['sage: ',r'\s*\.\.\. ']
257 InteractiveRunner.__init__(self,program,prompts,args)
303 InteractiveRunner.__init__(self,program,prompts,args,out,echo)
258
304
259 # Global usage string, to avoid indentation issues if typed in a function def.
305 # Global usage string, to avoid indentation issues if typed in a function def.
260 MAIN_USAGE = """
306 MAIN_USAGE = """
@@ -1,3 +1,15 b''
1 2007-01-27 Fernando Perez <Fernando.Perez@colorado.edu>
2
3 * IPython/irunner.py (InteractiveRunner.run_source): major updates
4 to irunner to allow it to correctly support real doctesting of
5 out-of-process ipython code.
6
7 * IPython/Magic.py (magic_cd): Make the setting of the terminal
8 title an option (-noterm_title) because it completely breaks
9 doctesting.
10
11 * IPython/demo.py: fix IPythonDemo class that was not actually working.
12
1 2007-01-24 Fernando Perez <Fernando.Perez@colorado.edu>
13 2007-01-24 Fernando Perez <Fernando.Perez@colorado.edu>
2
14
3 * IPython/irunner.py (main): fix small bug where extensions were
15 * IPython/irunner.py (main): fix small bug where extensions were
General Comments 0
You need to be logged in to leave comments. Login now