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 112 |
|
4 | $Id: Magic.py 1126 2006-02-06 02:31:40Z 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 | |
@@ -98,7 +98,7 b' license. To use profiling, please install"python2.3-profiler" from non-free.""")' | |||||
98 |
|
98 | |||
99 | def default_option(self,fn,optstr): |
|
99 | def default_option(self,fn,optstr): | |
100 | """Make an entry in the options_table for fn, with value optstr""" |
|
100 | """Make an entry in the options_table for fn, with value optstr""" | |
101 |
|
101 | |||
102 | if fn not in self.lsmagic(): |
|
102 | if fn not in self.lsmagic(): | |
103 | error("%s is not a magic function" % fn) |
|
103 | error("%s is not a magic function" % fn) | |
104 | self.options_table[fn] = optstr |
|
104 | self.options_table[fn] = optstr | |
@@ -129,12 +129,19 b' license. To use profiling, please install"python2.3-profiler" from non-free.""")' | |||||
129 | out.sort() |
|
129 | out.sort() | |
130 | return out |
|
130 | return out | |
131 |
|
131 | |||
132 | def extract_input_slices(self,slices): |
|
132 | def extract_input_slices(self,slices,raw=False): | |
133 | """Return as a string a set of input history slices. |
|
133 | """Return as a string a set of input history slices. | |
134 |
|
134 | |||
135 | The set of slices is given as a list of strings (like ['1','4:8','9'], |
|
135 | Inputs: | |
136 | since this function is for use by magic functions which get their |
|
136 | ||
137 | arguments as strings. |
|
137 | - slices: the set of slices is given as a list of strings (like | |
|
138 | ['1','4:8','9'], since this function is for use by magic functions | |||
|
139 | which get their arguments as strings. | |||
|
140 | ||||
|
141 | Optional inputs: | |||
|
142 | ||||
|
143 | - raw(False): by default, the processed input is used. If this is | |||
|
144 | true, the raw input history is used instead. | |||
138 |
|
145 | |||
139 | Note that slices can be called with two notations: |
|
146 | Note that slices can be called with two notations: | |
140 |
|
147 | |||
@@ -142,6 +149,11 b' license. To use profiling, please install"python2.3-profiler" from non-free.""")' | |||||
142 |
|
149 | |||
143 | N-M -> include items N..M (closed endpoint).""" |
|
150 | N-M -> include items N..M (closed endpoint).""" | |
144 |
|
151 | |||
|
152 | if raw: | |||
|
153 | hist = self.shell.input_hist_raw | |||
|
154 | else: | |||
|
155 | hist = self.shell.input_hist | |||
|
156 | ||||
145 | cmds = [] |
|
157 | cmds = [] | |
146 | for chunk in slices: |
|
158 | for chunk in slices: | |
147 | if ':' in chunk: |
|
159 | if ':' in chunk: | |
@@ -152,7 +164,7 b' license. To use profiling, please install"python2.3-profiler" from non-free.""")' | |||||
152 | else: |
|
164 | else: | |
153 | ini = int(chunk) |
|
165 | ini = int(chunk) | |
154 | fin = ini+1 |
|
166 | fin = ini+1 | |
155 |
cmds.append( |
|
167 | cmds.append(hist[ini:fin]) | |
156 | return cmds |
|
168 | return cmds | |
157 |
|
169 | |||
158 | def _ofind(self,oname): |
|
170 | def _ofind(self,oname): | |
@@ -1606,7 +1618,14 b' Currently the magic system has the following functions:\\n"""' | |||||
1606 | """Define a set of input lines as a macro for future re-execution. |
|
1618 | """Define a set of input lines as a macro for future re-execution. | |
1607 |
|
1619 | |||
1608 | Usage:\\ |
|
1620 | Usage:\\ | |
1609 | %macro name n1-n2 n3-n4 ... n5 .. n6 ... |
|
1621 | %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ... | |
|
1622 | ||||
|
1623 | Options: | |||
|
1624 | ||||
|
1625 | -r: use 'raw' input. By default, the 'processed' history is used, | |||
|
1626 | so that magics are loaded in their transformed version to valid | |||
|
1627 | Python. If this option is given, the raw input as typed as the | |||
|
1628 | command line is used instead. | |||
1610 |
|
1629 | |||
1611 | This will define a global variable called `name` which is a string |
|
1630 | This will define a global variable called `name` which is a string | |
1612 | made of joining the slices and lines you specify (n1,n2,... numbers |
|
1631 | made of joining the slices and lines you specify (n1,n2,... numbers | |
@@ -1657,10 +1676,10 b' Currently the magic system has the following functions:\\n"""' | |||||
1657 |
|
1676 | |||
1658 | In [60]: exec In[44:48]+In[49]""" |
|
1677 | In [60]: exec In[44:48]+In[49]""" | |
1659 |
|
1678 | |||
1660 |
args = parameter_s |
|
1679 | opts,args = self.parse_options(parameter_s,'r') | |
1661 | name,ranges = args[0], args[1:] |
|
1680 | name,ranges = args[0], args[1:] | |
1662 | #print 'rng',ranges # dbg |
|
1681 | #print 'rng',ranges # dbg | |
1663 | lines = self.extract_input_slices(ranges) |
|
1682 | lines = self.extract_input_slices(ranges,opts.has_key('r')) | |
1664 | macro = Macro(lines) |
|
1683 | macro = Macro(lines) | |
1665 | self.shell.user_ns.update({name:macro}) |
|
1684 | self.shell.user_ns.update({name:macro}) | |
1666 | print 'Macro `%s` created. To execute, type its name (without quotes).' % name |
|
1685 | print 'Macro `%s` created. To execute, type its name (without quotes).' % name | |
@@ -1671,7 +1690,14 b' Currently the magic system has the following functions:\\n"""' | |||||
1671 | """Save a set of lines to a given filename. |
|
1690 | """Save a set of lines to a given filename. | |
1672 |
|
1691 | |||
1673 | Usage:\\ |
|
1692 | Usage:\\ | |
1674 | %save filename n1-n2 n3-n4 ... n5 .. n6 ... |
|
1693 | %save [options] filename n1-n2 n3-n4 ... n5 .. n6 ... | |
|
1694 | ||||
|
1695 | Options: | |||
|
1696 | ||||
|
1697 | -r: use 'raw' input. By default, the 'processed' history is used, | |||
|
1698 | so that magics are loaded in their transformed version to valid | |||
|
1699 | Python. If this option is given, the raw input as typed as the | |||
|
1700 | command line is used instead. | |||
1675 |
|
1701 | |||
1676 | This function uses the same syntax as %macro for line extraction, but |
|
1702 | This function uses the same syntax as %macro for line extraction, but | |
1677 | instead of creating a macro it saves the resulting string to the |
|
1703 | instead of creating a macro it saves the resulting string to the | |
@@ -1680,7 +1706,7 b' Currently the magic system has the following functions:\\n"""' | |||||
1680 | It adds a '.py' extension to the file if you don't do so yourself, and |
|
1706 | It adds a '.py' extension to the file if you don't do so yourself, and | |
1681 | it asks for confirmation before overwriting existing files.""" |
|
1707 | it asks for confirmation before overwriting existing files.""" | |
1682 |
|
1708 | |||
1683 |
args = parameter_s |
|
1709 | opts,args = self.parse_options(parameter_s,'r') | |
1684 | fname,ranges = args[0], args[1:] |
|
1710 | fname,ranges = args[0], args[1:] | |
1685 | if not fname.endswith('.py'): |
|
1711 | if not fname.endswith('.py'): | |
1686 | fname += '.py' |
|
1712 | fname += '.py' | |
@@ -1689,7 +1715,7 b' Currently the magic system has the following functions:\\n"""' | |||||
1689 | if ans.lower() not in ['y','yes']: |
|
1715 | if ans.lower() not in ['y','yes']: | |
1690 | print 'Operation cancelled.' |
|
1716 | print 'Operation cancelled.' | |
1691 | return |
|
1717 | return | |
1692 | cmds = ''.join(self.extract_input_slices(ranges)) |
|
1718 | cmds = ''.join(self.extract_input_slices(ranges,opts.has_key('r'))) | |
1693 | f = file(fname,'w') |
|
1719 | f = file(fname,'w') | |
1694 | f.write(cmds) |
|
1720 | f.write(cmds) | |
1695 | f.close() |
|
1721 | f.close() | |
@@ -1742,6 +1768,13 b' Currently the magic system has the following functions:\\n"""' | |||||
1742 | it was used, regardless of how long ago (in your current session) it |
|
1768 | it was used, regardless of how long ago (in your current session) it | |
1743 | was. |
|
1769 | was. | |
1744 |
|
1770 | |||
|
1771 | -r: use 'raw' input. This option only applies to input taken from the | |||
|
1772 | user's history. By default, the 'processed' history is used, so that | |||
|
1773 | magics are loaded in their transformed version to valid Python. If | |||
|
1774 | this option is given, the raw input as typed as the command line is | |||
|
1775 | used instead. When you exit the editor, it will be executed by | |||
|
1776 | IPython's own processor. | |||
|
1777 | ||||
1745 | -x: do not execute the edited code immediately upon exit. This is |
|
1778 | -x: do not execute the edited code immediately upon exit. This is | |
1746 | mainly useful if you are editing programs which need to be called with |
|
1779 | mainly useful if you are editing programs which need to be called with | |
1747 | command line arguments, which you can then do using %run. |
|
1780 | command line arguments, which you can then do using %run. | |
@@ -1860,11 +1893,14 b' Currently the magic system has the following functions:\\n"""' | |||||
1860 | # custom exceptions |
|
1893 | # custom exceptions | |
1861 | class DataIsObject(Exception): pass |
|
1894 | class DataIsObject(Exception): pass | |
1862 |
|
1895 | |||
1863 | opts,args = self.parse_options(parameter_s,'px') |
|
1896 | opts,args = self.parse_options(parameter_s,'prx') | |
|
1897 | # Set a few locals from the options for convenience: | |||
|
1898 | opts_p = opts.has_key('p') | |||
|
1899 | opts_r = opts.has_key('r') | |||
1864 |
|
1900 | |||
1865 | # Default line number value |
|
1901 | # Default line number value | |
1866 | lineno = None |
|
1902 | lineno = None | |
1867 |
if opts |
|
1903 | if opts_p: | |
1868 | args = '_%s' % last_call[0] |
|
1904 | args = '_%s' % last_call[0] | |
1869 | if not self.shell.user_ns.has_key(args): |
|
1905 | if not self.shell.user_ns.has_key(args): | |
1870 | args = last_call[1] |
|
1906 | args = last_call[1] | |
@@ -1873,7 +1909,7 b' Currently the magic system has the following functions:\\n"""' | |||||
1873 | # let it be clobbered by successive '-p' calls. |
|
1909 | # let it be clobbered by successive '-p' calls. | |
1874 | try: |
|
1910 | try: | |
1875 | last_call[0] = self.shell.outputcache.prompt_count |
|
1911 | last_call[0] = self.shell.outputcache.prompt_count | |
1876 |
if not opts |
|
1912 | if not opts_p: | |
1877 | last_call[1] = parameter_s |
|
1913 | last_call[1] = parameter_s | |
1878 | except: |
|
1914 | except: | |
1879 | pass |
|
1915 | pass | |
@@ -1887,7 +1923,7 b' Currently the magic system has the following functions:\\n"""' | |||||
1887 | # This means that you can't edit files whose names begin with |
|
1923 | # This means that you can't edit files whose names begin with | |
1888 | # numbers this way. Tough. |
|
1924 | # numbers this way. Tough. | |
1889 | ranges = args.split() |
|
1925 | ranges = args.split() | |
1890 | data = ''.join(self.extract_input_slices(ranges)) |
|
1926 | data = ''.join(self.extract_input_slices(ranges,opts_r)) | |
1891 | elif args.endswith('.py'): |
|
1927 | elif args.endswith('.py'): | |
1892 | filename = make_filename(args) |
|
1928 | filename = make_filename(args) | |
1893 | data = '' |
|
1929 | data = '' | |
@@ -1955,7 +1991,10 b' Currently the magic system has the following functions:\\n"""' | |||||
1955 |
|
1991 | |||
1956 | else: |
|
1992 | else: | |
1957 | print 'done. Executing edited code...' |
|
1993 | print 'done. Executing edited code...' | |
1958 | self.shell.safe_execfile(filename,self.shell.user_ns) |
|
1994 | if opts_r: | |
|
1995 | self.shell.runlines(file_read(filename)) | |||
|
1996 | else: | |||
|
1997 | self.shell.safe_execfile(filename,self.shell.user_ns) | |||
1959 | if use_temp: |
|
1998 | if use_temp: | |
1960 | try: |
|
1999 | try: | |
1961 | return open(filename).read() |
|
2000 | return open(filename).read() |
@@ -1,9 +1,24 b'' | |||||
1 | """Module for interactive demos using IPython. |
|
1 | """Module for interactive demos using IPython. | |
2 |
|
2 | |||
3 |
This module implements a |
|
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 | ||||
|
8 | The classes are (see their docstrings for further details): | |||
|
9 | ||||
|
10 | - Demo: pure python demos | |||
|
11 | ||||
|
12 | - IPythonDemo: demos with input to be processed by IPython as if it had been | |||
|
13 | typed interactively (so magics work, as well as any other special syntax you | |||
|
14 | may have added via input prefilters). | |||
|
15 | ||||
|
16 | - LineDemo: single-line version of the Demo class. These demos are executed | |||
|
17 | one line at a time, and require no markup. | |||
|
18 | ||||
|
19 | - IPythonLineDemo: IPython version of the LineDemo class (the demo is | |||
|
20 | executed a line at a time, but processed via IPython). | |||
|
21 | ||||
7 |
|
22 | |||
8 | The file is run in its own empty namespace (though you can pass it a string of |
|
23 | The file is run in its own empty namespace (though you can pass it a string of | |
9 | arguments as if in a command line environment, and it will see those as |
|
24 | arguments as if in a command line environment, and it will see those as | |
@@ -54,12 +69,12 b' copy this into a file named ex_demo.py, and try running it via:' | |||||
54 |
|
69 | |||
55 | from IPython.demo import Demo |
|
70 | from IPython.demo import Demo | |
56 | d = Demo('ex_demo.py') |
|
71 | d = Demo('ex_demo.py') | |
57 |
d() <--- Call the d object (omit the parens if you have autocall |
|
72 | d() <--- Call the d object (omit the parens if you have autocall set to 2). | |
58 |
|
73 | |||
59 | Each time you call the demo object, it runs the next block. The demo object |
|
74 | Each time you call the demo object, it runs the next block. The demo object | |
60 |
has a few useful methods for navigation, like again(), jump(), seek() |
|
75 | has a few useful methods for navigation, like again(), edit(), jump(), seek() | |
61 |
back(). It can be reset for a new run via reset() or reloaded from disk |
|
76 | and back(). It can be reset for a new run via reset() or reloaded from disk | |
62 | case you've edited the source) via reload(). See their docstrings below. |
|
77 | (in case you've edited the source) via reload(). See their docstrings below. | |
63 |
|
78 | |||
64 | #################### EXAMPLE DEMO <ex_demo.py> ############################### |
|
79 | #################### EXAMPLE DEMO <ex_demo.py> ############################### | |
65 | '''A simple interactive demo to illustrate the use of IPython's Demo class.''' |
|
80 | '''A simple interactive demo to illustrate the use of IPython's Demo class.''' | |
@@ -95,9 +110,6 b" print 'z is now:', z" | |||||
95 |
|
110 | |||
96 | print 'bye!' |
|
111 | print 'bye!' | |
97 | ################### END EXAMPLE DEMO <ex_demo.py> ############################ |
|
112 | ################### END EXAMPLE DEMO <ex_demo.py> ############################ | |
98 |
|
||||
99 | WARNING: this module uses Python 2.3 features, so it won't work in 2.2 |
|
|||
100 | environments. |
|
|||
101 | """ |
|
113 | """ | |
102 | #***************************************************************************** |
|
114 | #***************************************************************************** | |
103 | # Copyright (C) 2005-2006 Fernando Perez. <Fernando.Perez@colorado.edu> |
|
115 | # Copyright (C) 2005-2006 Fernando Perez. <Fernando.Perez@colorado.edu> | |
@@ -108,13 +120,14 b' environments.' | |||||
108 | #***************************************************************************** |
|
120 | #***************************************************************************** | |
109 |
|
121 | |||
110 | import exceptions |
|
122 | import exceptions | |
|
123 | import os | |||
111 | import re |
|
124 | import re | |
112 | import sys |
|
125 | import sys | |
113 |
|
126 | |||
114 | from IPython.PyColorize import Parser |
|
127 | from IPython.PyColorize import Parser | |
115 | from IPython.genutils import marquee, shlex_split, file_read |
|
128 | from IPython.genutils import marquee, shlex_split, file_read, file_readlines | |
116 |
|
129 | |||
117 | __all__ = ['Demo','DemoError'] |
|
130 | __all__ = ['Demo','IPythonDemo','LineDemo','IPythonLineDemo','DemoError'] | |
118 |
|
131 | |||
119 | class DemoError(exceptions.Exception): pass |
|
132 | class DemoError(exceptions.Exception): pass | |
120 |
|
133 | |||
@@ -150,7 +163,7 b' class Demo:' | |||||
150 | can be changed at runtime simply by reassigning it to a boolean |
|
163 | can be changed at runtime simply by reassigning it to a boolean | |
151 | value. |
|
164 | value. | |
152 | """ |
|
165 | """ | |
153 |
|
166 | |||
154 | self.fname = fname |
|
167 | self.fname = fname | |
155 | self.sys_argv = [fname] + shlex_split(arg_str) |
|
168 | self.sys_argv = [fname] + shlex_split(arg_str) | |
156 | self.auto_all = auto_all |
|
169 | self.auto_all = auto_all | |
@@ -159,9 +172,11 b' class Demo:' | |||||
159 | # it ensures that things like color scheme and the like are always in |
|
172 | # it ensures that things like color scheme and the like are always in | |
160 | # sync with the ipython mode being used. This class is only meant to |
|
173 | # sync with the ipython mode being used. This class is only meant to | |
161 | # be used inside ipython anyways, so it's OK. |
|
174 | # be used inside ipython anyways, so it's OK. | |
162 | self.ip_showtb = __IPYTHON__.showtraceback |
|
|||
163 | self.ip_ns = __IPYTHON__.user_ns |
|
175 | self.ip_ns = __IPYTHON__.user_ns | |
164 | self.ip_colorize = __IPYTHON__.pycolorize |
|
176 | self.ip_colorize = __IPYTHON__.pycolorize | |
|
177 | self.ip_showtb = __IPYTHON__.showtraceback | |||
|
178 | self.ip_runlines = __IPYTHON__.runlines | |||
|
179 | self.shell = __IPYTHON__ | |||
165 |
|
180 | |||
166 | # load user data and initialize data structures |
|
181 | # load user data and initialize data structures | |
167 | self.reload() |
|
182 | self.reload() | |
@@ -211,6 +226,20 b' class Demo:' | |||||
211 | if index<0 or index>=self.nblocks: |
|
226 | if index<0 or index>=self.nblocks: | |
212 | raise ValueError('invalid block index %s' % index) |
|
227 | raise ValueError('invalid block index %s' % index) | |
213 |
|
228 | |||
|
229 | def _get_index(self,index): | |||
|
230 | """Get the current block index, validating and checking status. | |||
|
231 | ||||
|
232 | Returns None if the demo is finished""" | |||
|
233 | ||||
|
234 | if index is None: | |||
|
235 | if self.finished: | |||
|
236 | print 'Demo finished. Use reset() if you want to rerun it.' | |||
|
237 | return None | |||
|
238 | index = self.block_index | |||
|
239 | else: | |||
|
240 | self._validate_index(index) | |||
|
241 | return index | |||
|
242 | ||||
214 | def seek(self,index): |
|
243 | def seek(self,index): | |
215 | """Move the current seek pointer to the given block""" |
|
244 | """Move the current seek pointer to the given block""" | |
216 | self._validate_index(index) |
|
245 | self._validate_index(index) | |
@@ -230,15 +259,42 b' class Demo:' | |||||
230 | self.back(1) |
|
259 | self.back(1) | |
231 | self() |
|
260 | self() | |
232 |
|
261 | |||
|
262 | def edit(self,index=None): | |||
|
263 | """Edit a block. | |||
|
264 | ||||
|
265 | If no number is given, use the last block executed. | |||
|
266 | ||||
|
267 | This edits the in-memory copy of the demo, it does NOT modify the | |||
|
268 | original source file. If you want to do that, simply open the file in | |||
|
269 | an editor and use reload() when you make changes to the file. This | |||
|
270 | method is meant to let you change a block during a demonstration for | |||
|
271 | explanatory purposes, without damaging your original script.""" | |||
|
272 | ||||
|
273 | index = self._get_index(index) | |||
|
274 | if index is None: | |||
|
275 | return | |||
|
276 | # decrease the index by one (unless we're at the very beginning), so | |||
|
277 | # that the default demo.edit() call opens up the sblock we've last run | |||
|
278 | if index>0: | |||
|
279 | index -= 1 | |||
|
280 | ||||
|
281 | filename = self.shell.mktempfile(self.src_blocks[index]) | |||
|
282 | self.shell.hooks.editor(filename,1) | |||
|
283 | new_block = file_read(filename) | |||
|
284 | # update the source and colored block | |||
|
285 | self.src_blocks[index] = new_block | |||
|
286 | self.src_blocks_colored[index] = self.ip_colorize(new_block) | |||
|
287 | self.block_index = index | |||
|
288 | # call to run with the newly edited index | |||
|
289 | self() | |||
|
290 | ||||
233 | def show(self,index=None): |
|
291 | def show(self,index=None): | |
234 | """Show a single block on screen""" |
|
292 | """Show a single block on screen""" | |
|
293 | ||||
|
294 | index = self._get_index(index) | |||
235 | if index is None: |
|
295 | if index is None: | |
236 | if self.finished: |
|
296 | return | |
237 | print 'Demo finished. Use reset() if you want to rerun it.' |
|
297 | ||
238 | return |
|
|||
239 | index = self.block_index |
|
|||
240 | else: |
|
|||
241 | self._validate_index(index) |
|
|||
242 | print marquee('<%s> block # %s (%s remaining)' % |
|
298 | print marquee('<%s> block # %s (%s remaining)' % | |
243 | (self.fname,index,self.nblocks-index-1)) |
|
299 | (self.fname,index,self.nblocks-index-1)) | |
244 | print self.src_blocks_colored[index], |
|
300 | print self.src_blocks_colored[index], | |
@@ -259,7 +315,12 b' class Demo:' | |||||
259 | (fname,index,nblocks-index-1)) |
|
315 | (fname,index,nblocks-index-1)) | |
260 | print block, |
|
316 | print block, | |
261 | sys.stdout.flush() |
|
317 | sys.stdout.flush() | |
262 |
|
318 | |||
|
319 | def runlines(self,source): | |||
|
320 | """Execute a string with one or more lines of code""" | |||
|
321 | ||||
|
322 | exec source in self.user_ns | |||
|
323 | ||||
263 | def __call__(self,index=None): |
|
324 | def __call__(self,index=None): | |
264 | """run a block of the demo. |
|
325 | """run a block of the demo. | |
265 |
|
326 | |||
@@ -269,12 +330,9 b' class Demo:' | |||||
269 | prints 'Block n/N, and N is the total, so it would be very odd to use |
|
330 | prints 'Block n/N, and N is the total, so it would be very odd to use | |
270 | zero-indexing here.""" |
|
331 | zero-indexing here.""" | |
271 |
|
332 | |||
272 | if index is None and self.finished: |
|
333 | index = self._get_index(index) | |
273 | print 'Demo finished. Use reset() if you want to rerun it.' |
|
|||
274 | return |
|
|||
275 | if index is None: |
|
334 | if index is None: | |
276 | index = self.block_index |
|
335 | return | |
277 | self._validate_index(index) |
|
|||
278 | try: |
|
336 | try: | |
279 | next_block = self.src_blocks[index] |
|
337 | next_block = self.src_blocks[index] | |
280 | self.block_index += 1 |
|
338 | self.block_index += 1 | |
@@ -294,7 +352,7 b' class Demo:' | |||||
294 | try: |
|
352 | try: | |
295 | save_argv = sys.argv |
|
353 | save_argv = sys.argv | |
296 | sys.argv = self.sys_argv |
|
354 | sys.argv = self.sys_argv | |
297 |
|
|
355 | self.runlines(next_block) | |
298 | finally: |
|
356 | finally: | |
299 | sys.argv = save_argv |
|
357 | sys.argv = save_argv | |
300 |
|
358 | |||
@@ -309,3 +367,52 b' class Demo:' | |||||
309 | print marquee('Use reset() if you want to rerun it.') |
|
367 | print marquee('Use reset() if you want to rerun it.') | |
310 | self.finished = True |
|
368 | self.finished = True | |
311 |
|
369 | |||
|
370 | class IPythonDemo(Demo): | |||
|
371 | """Class for interactive demos with IPython's input processing applied. | |||
|
372 | ||||
|
373 | This subclasses Demo, but instead of executing each block by the Python | |||
|
374 | interpreter (via exec), it actually calls IPython on it, so that any input | |||
|
375 | filters which may be in place are applied to the input block. | |||
|
376 | ||||
|
377 | If you have an interactive environment which exposes special input | |||
|
378 | processing, you can use this class instead to write demo scripts which | |||
|
379 | operate exactly as if you had typed them interactively. The default Demo | |||
|
380 | class requires the input to be valid, pure Python code. | |||
|
381 | """ | |||
|
382 | ||||
|
383 | def runlines(self,source): | |||
|
384 | """Execute a string with one or more lines of code""" | |||
|
385 | ||||
|
386 | self.runlines(source) | |||
|
387 | ||||
|
388 | class LineDemo(Demo): | |||
|
389 | """Demo where each line is executed as a separate block. | |||
|
390 | ||||
|
391 | The input script should be valid Python code. | |||
|
392 | ||||
|
393 | This class doesn't require any markup at all, and it's meant for simple | |||
|
394 | scripts (with no nesting or any kind of indentation) which consist of | |||
|
395 | multiple lines of input to be executed, one at a time, as if they had been | |||
|
396 | typed in the interactive prompt.""" | |||
|
397 | ||||
|
398 | def reload(self): | |||
|
399 | """Reload source from disk and initialize state.""" | |||
|
400 | # read data and parse into blocks | |||
|
401 | src_b = [l for l in file_readlines(self.fname) if l.strip()] | |||
|
402 | nblocks = len(src_b) | |||
|
403 | self.src = os.linesep.join(file_readlines(self.fname)) | |||
|
404 | self._silent = [False]*nblocks | |||
|
405 | self._auto = [True]*nblocks | |||
|
406 | self.auto_all = True | |||
|
407 | self.nblocks = nblocks | |||
|
408 | self.src_blocks = src_b | |||
|
409 | ||||
|
410 | # also build syntax-highlighted source | |||
|
411 | self.src_blocks_colored = map(self.ip_colorize,self.src_blocks) | |||
|
412 | ||||
|
413 | # ensure clean namespace and seek offset | |||
|
414 | self.reset() | |||
|
415 | ||||
|
416 | class IPythonLineDemo(IPythonDemo,LineDemo): | |||
|
417 | """Variant of the LineDemo class whose input is processed by IPython.""" | |||
|
418 | pass |
@@ -5,7 +5,7 b' General purpose utilities.' | |||||
5 | This is a grab-bag of stuff I find useful in most programs I write. Some of |
|
5 | This is a grab-bag of stuff I find useful in most programs I write. Some of | |
6 | these things are also convenient when working at the command line. |
|
6 | these things are also convenient when working at the command line. | |
7 |
|
7 | |||
8 |
$Id: genutils.py 11 |
|
8 | $Id: genutils.py 1126 2006-02-06 02:31:40Z fperez $""" | |
9 |
|
9 | |||
10 | #***************************************************************************** |
|
10 | #***************************************************************************** | |
11 | # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu> |
|
11 | # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu> | |
@@ -529,11 +529,18 b' def filefind(fname,alt_dirs = None):' | |||||
529 | #---------------------------------------------------------------------------- |
|
529 | #---------------------------------------------------------------------------- | |
530 | def file_read(filename): |
|
530 | def file_read(filename): | |
531 | """Read a file and close it. Returns the file source.""" |
|
531 | """Read a file and close it. Returns the file source.""" | |
532 | fobj=open(filename,'r'); |
|
532 | fobj = open(filename,'r'); | |
533 | source = fobj.read(); |
|
533 | source = fobj.read(); | |
534 | fobj.close() |
|
534 | fobj.close() | |
535 | return source |
|
535 | return source | |
536 |
|
536 | |||
|
537 | def file_readlines(filename): | |||
|
538 | """Read a file and close it. Returns the file source using readlines().""" | |||
|
539 | fobj = open(filename,'r'); | |||
|
540 | lines = fobj.readlines(); | |||
|
541 | fobj.close() | |||
|
542 | return lines | |||
|
543 | ||||
537 | #---------------------------------------------------------------------------- |
|
544 | #---------------------------------------------------------------------------- | |
538 | def target_outdated(target,deps): |
|
545 | def target_outdated(target,deps): | |
539 | """Determine whether a target is out of date. |
|
546 | """Determine whether a target is out of date. |
@@ -1,3 +1,20 b'' | |||||
|
1 | 2006-02-05 Fernando Perez <Fernando.Perez@colorado.edu> | |||
|
2 | ||||
|
3 | * IPython/demo.py (IPythonDemo): Add new classes to the demo | |||
|
4 | facilities, for demos processed by the IPython input filter | |||
|
5 | (IPythonDemo), and for running a script one-line-at-a-time as a | |||
|
6 | demo, both for pure Python (LineDemo) and for IPython-processed | |||
|
7 | input (IPythonLineDemo). After a request by Dave Kohel, from the | |||
|
8 | SAGE team. | |||
|
9 | (Demo.edit): added and edit() method to the demo objects, to edit | |||
|
10 | the in-memory copy of the last executed block. | |||
|
11 | ||||
|
12 | * IPython/Magic.py (magic_edit): add '-r' option for 'raw' | |||
|
13 | processing to %edit, %macro and %save. These commands can now be | |||
|
14 | invoked on the unprocessed input as it was typed by the user | |||
|
15 | (without any prefilters applied). After requests by the SAGE team | |||
|
16 | at SAGE days 2006: http://modular.ucsd.edu/sage/days1/schedule.html. | |||
|
17 | ||||
1 | 2006-02-01 Ville Vainio <vivainio@gmail.com> |
|
18 | 2006-02-01 Ville Vainio <vivainio@gmail.com> | |
2 |
|
19 | |||
3 | * setup.py, eggsetup.py: easy_install ipython==dev works |
|
20 | * setup.py, eggsetup.py: easy_install ipython==dev works |
General Comments 0
You need to be logged in to leave comments.
Login now