##// END OF EJS Templates
Inline trivial file_read() function
Thomas Kluyver -
Show More
@@ -1,558 +1,559 b''
1 """Implementation of code management magic functions.
1 """Implementation of code management magic functions.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2012 The IPython Development Team.
4 # Copyright (c) 2012 The IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7 #
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 # Stdlib
15 # Stdlib
16 import inspect
16 import inspect
17 import io
17 import io
18 import os
18 import os
19 import re
19 import re
20 import sys
20 import sys
21
21
22 # Our own packages
22 # Our own packages
23 from IPython.core.error import TryNext, StdinNotImplementedError, UsageError
23 from IPython.core.error import TryNext, StdinNotImplementedError, UsageError
24 from IPython.core.macro import Macro
24 from IPython.core.macro import Macro
25 from IPython.core.magic import Magics, magics_class, line_magic
25 from IPython.core.magic import Magics, magics_class, line_magic
26 from IPython.core.oinspect import find_file, find_source_lines
26 from IPython.core.oinspect import find_file, find_source_lines
27 from IPython.testing.skipdoctest import skip_doctest
27 from IPython.testing.skipdoctest import skip_doctest
28 from IPython.utils import py3compat
28 from IPython.utils import py3compat
29 from IPython.utils.contexts import preserve_keys
29 from IPython.utils.contexts import preserve_keys
30 from IPython.utils.io import file_read
31 from IPython.utils.path import get_py_filename, unquote_filename
30 from IPython.utils.path import get_py_filename, unquote_filename
32 from IPython.utils.warn import warn
31 from IPython.utils.warn import warn
33
32
34 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
35 # Magic implementation classes
34 # Magic implementation classes
36 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
37
36
38 # Used for exception handling in magic_edit
37 # Used for exception handling in magic_edit
39 class MacroToEdit(ValueError): pass
38 class MacroToEdit(ValueError): pass
40
39
41 ipython_input_pat = re.compile(r"<ipython\-input\-(\d+)-[a-z\d]+>$")
40 ipython_input_pat = re.compile(r"<ipython\-input\-(\d+)-[a-z\d]+>$")
42
41
43 class InteractivelyDefined(Exception):
42 class InteractivelyDefined(Exception):
44 """Exception for interactively defined variable in magic_edit"""
43 """Exception for interactively defined variable in magic_edit"""
45 def __init__(self, index):
44 def __init__(self, index):
46 self.index = index
45 self.index = index
47
46
48
47
49 @magics_class
48 @magics_class
50 class CodeMagics(Magics):
49 class CodeMagics(Magics):
51 """Magics related to code management (loading, saving, editing, ...)."""
50 """Magics related to code management (loading, saving, editing, ...)."""
52
51
53 @line_magic
52 @line_magic
54 def save(self, parameter_s=''):
53 def save(self, parameter_s=''):
55 """Save a set of lines or a macro to a given filename.
54 """Save a set of lines or a macro to a given filename.
56
55
57 Usage:\\
56 Usage:\\
58 %save [options] filename n1-n2 n3-n4 ... n5 .. n6 ...
57 %save [options] filename n1-n2 n3-n4 ... n5 .. n6 ...
59
58
60 Options:
59 Options:
61
60
62 -r: use 'raw' input. By default, the 'processed' history is used,
61 -r: use 'raw' input. By default, the 'processed' history is used,
63 so that magics are loaded in their transformed version to valid
62 so that magics are loaded in their transformed version to valid
64 Python. If this option is given, the raw input as typed as the
63 Python. If this option is given, the raw input as typed as the
65 command line is used instead.
64 command line is used instead.
66
65
67 -f: force overwrite. If file exists, %save will prompt for overwrite
66 -f: force overwrite. If file exists, %save will prompt for overwrite
68 unless -f is given.
67 unless -f is given.
69
68
70 -a: append to the file instead of overwriting it.
69 -a: append to the file instead of overwriting it.
71
70
72 This function uses the same syntax as %history for input ranges,
71 This function uses the same syntax as %history for input ranges,
73 then saves the lines to the filename you specify.
72 then saves the lines to the filename you specify.
74
73
75 It adds a '.py' extension to the file if you don't do so yourself, and
74 It adds a '.py' extension to the file if you don't do so yourself, and
76 it asks for confirmation before overwriting existing files.
75 it asks for confirmation before overwriting existing files.
77
76
78 If `-r` option is used, the default extension is `.ipy`.
77 If `-r` option is used, the default extension is `.ipy`.
79 """
78 """
80
79
81 opts,args = self.parse_options(parameter_s,'fra',mode='list')
80 opts,args = self.parse_options(parameter_s,'fra',mode='list')
82 if not args:
81 if not args:
83 raise UsageError('Missing filename.')
82 raise UsageError('Missing filename.')
84 raw = 'r' in opts
83 raw = 'r' in opts
85 force = 'f' in opts
84 force = 'f' in opts
86 append = 'a' in opts
85 append = 'a' in opts
87 mode = 'a' if append else 'w'
86 mode = 'a' if append else 'w'
88 ext = u'.ipy' if raw else u'.py'
87 ext = u'.ipy' if raw else u'.py'
89 fname, codefrom = unquote_filename(args[0]), " ".join(args[1:])
88 fname, codefrom = unquote_filename(args[0]), " ".join(args[1:])
90 if not fname.endswith((u'.py',u'.ipy')):
89 if not fname.endswith((u'.py',u'.ipy')):
91 fname += ext
90 fname += ext
92 file_exists = os.path.isfile(fname)
91 file_exists = os.path.isfile(fname)
93 if file_exists and not force and not append:
92 if file_exists and not force and not append:
94 try:
93 try:
95 overwrite = self.shell.ask_yes_no('File `%s` exists. Overwrite (y/[N])? ' % fname, default='n')
94 overwrite = self.shell.ask_yes_no('File `%s` exists. Overwrite (y/[N])? ' % fname, default='n')
96 except StdinNotImplementedError:
95 except StdinNotImplementedError:
97 print "File `%s` exists. Use `%%save -f %s` to force overwrite" % (fname, parameter_s)
96 print "File `%s` exists. Use `%%save -f %s` to force overwrite" % (fname, parameter_s)
98 return
97 return
99 if not overwrite :
98 if not overwrite :
100 print 'Operation cancelled.'
99 print 'Operation cancelled.'
101 return
100 return
102 try:
101 try:
103 cmds = self.shell.find_user_code(codefrom,raw)
102 cmds = self.shell.find_user_code(codefrom,raw)
104 except (TypeError, ValueError) as e:
103 except (TypeError, ValueError) as e:
105 print e.args[0]
104 print e.args[0]
106 return
105 return
107 out = py3compat.cast_unicode(cmds)
106 out = py3compat.cast_unicode(cmds)
108 with io.open(fname, mode, encoding="utf-8") as f:
107 with io.open(fname, mode, encoding="utf-8") as f:
109 if not file_exists or not append:
108 if not file_exists or not append:
110 f.write(u"# coding: utf-8\n")
109 f.write(u"# coding: utf-8\n")
111 f.write(out)
110 f.write(out)
112 # make sure we end on a newline
111 # make sure we end on a newline
113 if not out.endswith(u'\n'):
112 if not out.endswith(u'\n'):
114 f.write(u'\n')
113 f.write(u'\n')
115 print 'The following commands were written to file `%s`:' % fname
114 print 'The following commands were written to file `%s`:' % fname
116 print cmds
115 print cmds
117
116
118 @line_magic
117 @line_magic
119 def pastebin(self, parameter_s=''):
118 def pastebin(self, parameter_s=''):
120 """Upload code to Github's Gist paste bin, returning the URL.
119 """Upload code to Github's Gist paste bin, returning the URL.
121
120
122 Usage:\\
121 Usage:\\
123 %pastebin [-d "Custom description"] 1-7
122 %pastebin [-d "Custom description"] 1-7
124
123
125 The argument can be an input history range, a filename, or the name of a
124 The argument can be an input history range, a filename, or the name of a
126 string or macro.
125 string or macro.
127
126
128 Options:
127 Options:
129
128
130 -d: Pass a custom description for the gist. The default will say
129 -d: Pass a custom description for the gist. The default will say
131 "Pasted from IPython".
130 "Pasted from IPython".
132 """
131 """
133 opts, args = self.parse_options(parameter_s, 'd:')
132 opts, args = self.parse_options(parameter_s, 'd:')
134
133
135 try:
134 try:
136 code = self.shell.find_user_code(args)
135 code = self.shell.find_user_code(args)
137 except (ValueError, TypeError) as e:
136 except (ValueError, TypeError) as e:
138 print e.args[0]
137 print e.args[0]
139 return
138 return
140
139
141 from urllib2 import urlopen # Deferred import
140 from urllib2 import urlopen # Deferred import
142 import json
141 import json
143 post_data = json.dumps({
142 post_data = json.dumps({
144 "description": opts.get('d', "Pasted from IPython"),
143 "description": opts.get('d', "Pasted from IPython"),
145 "public": True,
144 "public": True,
146 "files": {
145 "files": {
147 "file1.py": {
146 "file1.py": {
148 "content": code
147 "content": code
149 }
148 }
150 }
149 }
151 }).encode('utf-8')
150 }).encode('utf-8')
152
151
153 response = urlopen("https://api.github.com/gists", post_data)
152 response = urlopen("https://api.github.com/gists", post_data)
154 response_data = json.loads(response.read().decode('utf-8'))
153 response_data = json.loads(response.read().decode('utf-8'))
155 return response_data['html_url']
154 return response_data['html_url']
156
155
157 @line_magic
156 @line_magic
158 def loadpy(self, arg_s):
157 def loadpy(self, arg_s):
159 """Alias of `%load`
158 """Alias of `%load`
160
159
161 `%loadpy` has gained some flexibility and droped the requirement of a `.py`
160 `%loadpy` has gained some flexibility and droped the requirement of a `.py`
162 extension. So it has been renamed simply into %load. You can look at
161 extension. So it has been renamed simply into %load. You can look at
163 `%load`'s docstring for more info.
162 `%load`'s docstring for more info.
164 """
163 """
165 self.load(arg_s)
164 self.load(arg_s)
166
165
167 @line_magic
166 @line_magic
168 def load(self, arg_s):
167 def load(self, arg_s):
169 """Load code into the current frontend.
168 """Load code into the current frontend.
170
169
171 Usage:\\
170 Usage:\\
172 %load [options] source
171 %load [options] source
173
172
174 where source can be a filename, URL, input history range or macro
173 where source can be a filename, URL, input history range or macro
175
174
176 Options:
175 Options:
177 --------
176 --------
178 -y : Don't ask confirmation for loading source above 200 000 characters.
177 -y : Don't ask confirmation for loading source above 200 000 characters.
179
178
180 This magic command can either take a local filename, a URL, an history
179 This magic command can either take a local filename, a URL, an history
181 range (see %history) or a macro as argument, it will prompt for
180 range (see %history) or a macro as argument, it will prompt for
182 confirmation before loading source with more than 200 000 characters, unless
181 confirmation before loading source with more than 200 000 characters, unless
183 -y flag is passed or if the frontend does not support raw_input::
182 -y flag is passed or if the frontend does not support raw_input::
184
183
185 %load myscript.py
184 %load myscript.py
186 %load 7-27
185 %load 7-27
187 %load myMacro
186 %load myMacro
188 %load http://www.example.com/myscript.py
187 %load http://www.example.com/myscript.py
189 """
188 """
190 opts,args = self.parse_options(arg_s,'y')
189 opts,args = self.parse_options(arg_s,'y')
191 if not args:
190 if not args:
192 raise UsageError('Missing filename, URL, input history range, '
191 raise UsageError('Missing filename, URL, input history range, '
193 'or macro.')
192 'or macro.')
194
193
195 contents = self.shell.find_user_code(args)
194 contents = self.shell.find_user_code(args)
196 l = len(contents)
195 l = len(contents)
197
196
198 # 200 000 is ~ 2500 full 80 caracter lines
197 # 200 000 is ~ 2500 full 80 caracter lines
199 # so in average, more than 5000 lines
198 # so in average, more than 5000 lines
200 if l > 200000 and 'y' not in opts:
199 if l > 200000 and 'y' not in opts:
201 try:
200 try:
202 ans = self.shell.ask_yes_no(("The text you're trying to load seems pretty big"\
201 ans = self.shell.ask_yes_no(("The text you're trying to load seems pretty big"\
203 " (%d characters). Continue (y/[N]) ?" % l), default='n' )
202 " (%d characters). Continue (y/[N]) ?" % l), default='n' )
204 except StdinNotImplementedError:
203 except StdinNotImplementedError:
205 #asume yes if raw input not implemented
204 #asume yes if raw input not implemented
206 ans = True
205 ans = True
207
206
208 if ans is False :
207 if ans is False :
209 print 'Operation cancelled.'
208 print 'Operation cancelled.'
210 return
209 return
211
210
212 self.shell.set_next_input(contents)
211 self.shell.set_next_input(contents)
213
212
214 @staticmethod
213 @staticmethod
215 def _find_edit_target(shell, args, opts, last_call):
214 def _find_edit_target(shell, args, opts, last_call):
216 """Utility method used by magic_edit to find what to edit."""
215 """Utility method used by magic_edit to find what to edit."""
217
216
218 def make_filename(arg):
217 def make_filename(arg):
219 "Make a filename from the given args"
218 "Make a filename from the given args"
220 arg = unquote_filename(arg)
219 arg = unquote_filename(arg)
221 try:
220 try:
222 filename = get_py_filename(arg)
221 filename = get_py_filename(arg)
223 except IOError:
222 except IOError:
224 # If it ends with .py but doesn't already exist, assume we want
223 # If it ends with .py but doesn't already exist, assume we want
225 # a new file.
224 # a new file.
226 if arg.endswith('.py'):
225 if arg.endswith('.py'):
227 filename = arg
226 filename = arg
228 else:
227 else:
229 filename = None
228 filename = None
230 return filename
229 return filename
231
230
232 # Set a few locals from the options for convenience:
231 # Set a few locals from the options for convenience:
233 opts_prev = 'p' in opts
232 opts_prev = 'p' in opts
234 opts_raw = 'r' in opts
233 opts_raw = 'r' in opts
235
234
236 # custom exceptions
235 # custom exceptions
237 class DataIsObject(Exception): pass
236 class DataIsObject(Exception): pass
238
237
239 # Default line number value
238 # Default line number value
240 lineno = opts.get('n',None)
239 lineno = opts.get('n',None)
241
240
242 if opts_prev:
241 if opts_prev:
243 args = '_%s' % last_call[0]
242 args = '_%s' % last_call[0]
244 if args not in shell.user_ns:
243 if args not in shell.user_ns:
245 args = last_call[1]
244 args = last_call[1]
246
245
247 # by default this is done with temp files, except when the given
246 # by default this is done with temp files, except when the given
248 # arg is a filename
247 # arg is a filename
249 use_temp = True
248 use_temp = True
250
249
251 data = ''
250 data = ''
252
251
253 # First, see if the arguments should be a filename.
252 # First, see if the arguments should be a filename.
254 filename = make_filename(args)
253 filename = make_filename(args)
255 if filename:
254 if filename:
256 use_temp = False
255 use_temp = False
257 elif args:
256 elif args:
258 # Mode where user specifies ranges of lines, like in %macro.
257 # Mode where user specifies ranges of lines, like in %macro.
259 data = shell.extract_input_lines(args, opts_raw)
258 data = shell.extract_input_lines(args, opts_raw)
260 if not data:
259 if not data:
261 try:
260 try:
262 # Load the parameter given as a variable. If not a string,
261 # Load the parameter given as a variable. If not a string,
263 # process it as an object instead (below)
262 # process it as an object instead (below)
264
263
265 #print '*** args',args,'type',type(args) # dbg
264 #print '*** args',args,'type',type(args) # dbg
266 data = eval(args, shell.user_ns)
265 data = eval(args, shell.user_ns)
267 if not isinstance(data, basestring):
266 if not isinstance(data, basestring):
268 raise DataIsObject
267 raise DataIsObject
269
268
270 except (NameError,SyntaxError):
269 except (NameError,SyntaxError):
271 # given argument is not a variable, try as a filename
270 # given argument is not a variable, try as a filename
272 filename = make_filename(args)
271 filename = make_filename(args)
273 if filename is None:
272 if filename is None:
274 warn("Argument given (%s) can't be found as a variable "
273 warn("Argument given (%s) can't be found as a variable "
275 "or as a filename." % args)
274 "or as a filename." % args)
276 return (None, None, None)
275 return (None, None, None)
277 use_temp = False
276 use_temp = False
278
277
279 except DataIsObject:
278 except DataIsObject:
280 # macros have a special edit function
279 # macros have a special edit function
281 if isinstance(data, Macro):
280 if isinstance(data, Macro):
282 raise MacroToEdit(data)
281 raise MacroToEdit(data)
283
282
284 # For objects, try to edit the file where they are defined
283 # For objects, try to edit the file where they are defined
285 filename = find_file(data)
284 filename = find_file(data)
286 if filename:
285 if filename:
287 if 'fakemodule' in filename.lower() and \
286 if 'fakemodule' in filename.lower() and \
288 inspect.isclass(data):
287 inspect.isclass(data):
289 # class created by %edit? Try to find source
288 # class created by %edit? Try to find source
290 # by looking for method definitions instead, the
289 # by looking for method definitions instead, the
291 # __module__ in those classes is FakeModule.
290 # __module__ in those classes is FakeModule.
292 attrs = [getattr(data, aname) for aname in dir(data)]
291 attrs = [getattr(data, aname) for aname in dir(data)]
293 for attr in attrs:
292 for attr in attrs:
294 if not inspect.ismethod(attr):
293 if not inspect.ismethod(attr):
295 continue
294 continue
296 filename = find_file(attr)
295 filename = find_file(attr)
297 if filename and \
296 if filename and \
298 'fakemodule' not in filename.lower():
297 'fakemodule' not in filename.lower():
299 # change the attribute to be the edit
298 # change the attribute to be the edit
300 # target instead
299 # target instead
301 data = attr
300 data = attr
302 break
301 break
303
302
304 m = ipython_input_pat.match(os.path.basename(filename))
303 m = ipython_input_pat.match(os.path.basename(filename))
305 if m:
304 if m:
306 raise InteractivelyDefined(int(m.groups()[0]))
305 raise InteractivelyDefined(int(m.groups()[0]))
307
306
308 datafile = 1
307 datafile = 1
309 if filename is None:
308 if filename is None:
310 filename = make_filename(args)
309 filename = make_filename(args)
311 datafile = 1
310 datafile = 1
312 if filename is not None:
311 if filename is not None:
313 # only warn about this if we get a real name
312 # only warn about this if we get a real name
314 warn('Could not find file where `%s` is defined.\n'
313 warn('Could not find file where `%s` is defined.\n'
315 'Opening a file named `%s`' % (args, filename))
314 'Opening a file named `%s`' % (args, filename))
316 # Now, make sure we can actually read the source (if it was
315 # Now, make sure we can actually read the source (if it was
317 # in a temp file it's gone by now).
316 # in a temp file it's gone by now).
318 if datafile:
317 if datafile:
319 if lineno is None:
318 if lineno is None:
320 lineno = find_source_lines(data)
319 lineno = find_source_lines(data)
321 if lineno is None:
320 if lineno is None:
322 filename = make_filename(args)
321 filename = make_filename(args)
323 if filename is None:
322 if filename is None:
324 warn('The file where `%s` was defined '
323 warn('The file where `%s` was defined '
325 'cannot be read or found.' % data)
324 'cannot be read or found.' % data)
326 return (None, None, None)
325 return (None, None, None)
327 use_temp = False
326 use_temp = False
328
327
329 if use_temp:
328 if use_temp:
330 filename = shell.mktempfile(data)
329 filename = shell.mktempfile(data)
331 print 'IPython will make a temporary file named:',filename
330 print 'IPython will make a temporary file named:',filename
332
331
333 # use last_call to remember the state of the previous call, but don't
332 # use last_call to remember the state of the previous call, but don't
334 # let it be clobbered by successive '-p' calls.
333 # let it be clobbered by successive '-p' calls.
335 try:
334 try:
336 last_call[0] = shell.displayhook.prompt_count
335 last_call[0] = shell.displayhook.prompt_count
337 if not opts_prev:
336 if not opts_prev:
338 last_call[1] = args
337 last_call[1] = args
339 except:
338 except:
340 pass
339 pass
341
340
342
341
343 return filename, lineno, use_temp
342 return filename, lineno, use_temp
344
343
345 def _edit_macro(self,mname,macro):
344 def _edit_macro(self,mname,macro):
346 """open an editor with the macro data in a file"""
345 """open an editor with the macro data in a file"""
347 filename = self.shell.mktempfile(macro.value)
346 filename = self.shell.mktempfile(macro.value)
348 self.shell.hooks.editor(filename)
347 self.shell.hooks.editor(filename)
349
348
350 # and make a new macro object, to replace the old one
349 # and make a new macro object, to replace the old one
351 mfile = open(filename)
350 mfile = open(filename)
352 mvalue = mfile.read()
351 mvalue = mfile.read()
353 mfile.close()
352 mfile.close()
354 self.shell.user_ns[mname] = Macro(mvalue)
353 self.shell.user_ns[mname] = Macro(mvalue)
355
354
356 @skip_doctest
355 @skip_doctest
357 @line_magic
356 @line_magic
358 def edit(self, parameter_s='',last_call=['','']):
357 def edit(self, parameter_s='',last_call=['','']):
359 """Bring up an editor and execute the resulting code.
358 """Bring up an editor and execute the resulting code.
360
359
361 Usage:
360 Usage:
362 %edit [options] [args]
361 %edit [options] [args]
363
362
364 %edit runs IPython's editor hook. The default version of this hook is
363 %edit runs IPython's editor hook. The default version of this hook is
365 set to call the editor specified by your $EDITOR environment variable.
364 set to call the editor specified by your $EDITOR environment variable.
366 If this isn't found, it will default to vi under Linux/Unix and to
365 If this isn't found, it will default to vi under Linux/Unix and to
367 notepad under Windows. See the end of this docstring for how to change
366 notepad under Windows. See the end of this docstring for how to change
368 the editor hook.
367 the editor hook.
369
368
370 You can also set the value of this editor via the
369 You can also set the value of this editor via the
371 ``TerminalInteractiveShell.editor`` option in your configuration file.
370 ``TerminalInteractiveShell.editor`` option in your configuration file.
372 This is useful if you wish to use a different editor from your typical
371 This is useful if you wish to use a different editor from your typical
373 default with IPython (and for Windows users who typically don't set
372 default with IPython (and for Windows users who typically don't set
374 environment variables).
373 environment variables).
375
374
376 This command allows you to conveniently edit multi-line code right in
375 This command allows you to conveniently edit multi-line code right in
377 your IPython session.
376 your IPython session.
378
377
379 If called without arguments, %edit opens up an empty editor with a
378 If called without arguments, %edit opens up an empty editor with a
380 temporary file and will execute the contents of this file when you
379 temporary file and will execute the contents of this file when you
381 close it (don't forget to save it!).
380 close it (don't forget to save it!).
382
381
383
382
384 Options:
383 Options:
385
384
386 -n <number>: open the editor at a specified line number. By default,
385 -n <number>: open the editor at a specified line number. By default,
387 the IPython editor hook uses the unix syntax 'editor +N filename', but
386 the IPython editor hook uses the unix syntax 'editor +N filename', but
388 you can configure this by providing your own modified hook if your
387 you can configure this by providing your own modified hook if your
389 favorite editor supports line-number specifications with a different
388 favorite editor supports line-number specifications with a different
390 syntax.
389 syntax.
391
390
392 -p: this will call the editor with the same data as the previous time
391 -p: this will call the editor with the same data as the previous time
393 it was used, regardless of how long ago (in your current session) it
392 it was used, regardless of how long ago (in your current session) it
394 was.
393 was.
395
394
396 -r: use 'raw' input. This option only applies to input taken from the
395 -r: use 'raw' input. This option only applies to input taken from the
397 user's history. By default, the 'processed' history is used, so that
396 user's history. By default, the 'processed' history is used, so that
398 magics are loaded in their transformed version to valid Python. If
397 magics are loaded in their transformed version to valid Python. If
399 this option is given, the raw input as typed as the command line is
398 this option is given, the raw input as typed as the command line is
400 used instead. When you exit the editor, it will be executed by
399 used instead. When you exit the editor, it will be executed by
401 IPython's own processor.
400 IPython's own processor.
402
401
403 -x: do not execute the edited code immediately upon exit. This is
402 -x: do not execute the edited code immediately upon exit. This is
404 mainly useful if you are editing programs which need to be called with
403 mainly useful if you are editing programs which need to be called with
405 command line arguments, which you can then do using %run.
404 command line arguments, which you can then do using %run.
406
405
407
406
408 Arguments:
407 Arguments:
409
408
410 If arguments are given, the following possibilities exist:
409 If arguments are given, the following possibilities exist:
411
410
412 - If the argument is a filename, IPython will load that into the
411 - If the argument is a filename, IPython will load that into the
413 editor. It will execute its contents with execfile() when you exit,
412 editor. It will execute its contents with execfile() when you exit,
414 loading any code in the file into your interactive namespace.
413 loading any code in the file into your interactive namespace.
415
414
416 - The arguments are ranges of input history, e.g. "7 ~1/4-6".
415 - The arguments are ranges of input history, e.g. "7 ~1/4-6".
417 The syntax is the same as in the %history magic.
416 The syntax is the same as in the %history magic.
418
417
419 - If the argument is a string variable, its contents are loaded
418 - If the argument is a string variable, its contents are loaded
420 into the editor. You can thus edit any string which contains
419 into the editor. You can thus edit any string which contains
421 python code (including the result of previous edits).
420 python code (including the result of previous edits).
422
421
423 - If the argument is the name of an object (other than a string),
422 - If the argument is the name of an object (other than a string),
424 IPython will try to locate the file where it was defined and open the
423 IPython will try to locate the file where it was defined and open the
425 editor at the point where it is defined. You can use `%edit function`
424 editor at the point where it is defined. You can use `%edit function`
426 to load an editor exactly at the point where 'function' is defined,
425 to load an editor exactly at the point where 'function' is defined,
427 edit it and have the file be executed automatically.
426 edit it and have the file be executed automatically.
428
427
429 - If the object is a macro (see %macro for details), this opens up your
428 - If the object is a macro (see %macro for details), this opens up your
430 specified editor with a temporary file containing the macro's data.
429 specified editor with a temporary file containing the macro's data.
431 Upon exit, the macro is reloaded with the contents of the file.
430 Upon exit, the macro is reloaded with the contents of the file.
432
431
433 Note: opening at an exact line is only supported under Unix, and some
432 Note: opening at an exact line is only supported under Unix, and some
434 editors (like kedit and gedit up to Gnome 2.8) do not understand the
433 editors (like kedit and gedit up to Gnome 2.8) do not understand the
435 '+NUMBER' parameter necessary for this feature. Good editors like
434 '+NUMBER' parameter necessary for this feature. Good editors like
436 (X)Emacs, vi, jed, pico and joe all do.
435 (X)Emacs, vi, jed, pico and joe all do.
437
436
438 After executing your code, %edit will return as output the code you
437 After executing your code, %edit will return as output the code you
439 typed in the editor (except when it was an existing file). This way
438 typed in the editor (except when it was an existing file). This way
440 you can reload the code in further invocations of %edit as a variable,
439 you can reload the code in further invocations of %edit as a variable,
441 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
440 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
442 the output.
441 the output.
443
442
444 Note that %edit is also available through the alias %ed.
443 Note that %edit is also available through the alias %ed.
445
444
446 This is an example of creating a simple function inside the editor and
445 This is an example of creating a simple function inside the editor and
447 then modifying it. First, start up the editor::
446 then modifying it. First, start up the editor::
448
447
449 In [1]: edit
448 In [1]: edit
450 Editing... done. Executing edited code...
449 Editing... done. Executing edited code...
451 Out[1]: 'def foo():\\n print "foo() was defined in an editing
450 Out[1]: 'def foo():\\n print "foo() was defined in an editing
452 session"\\n'
451 session"\\n'
453
452
454 We can then call the function foo()::
453 We can then call the function foo()::
455
454
456 In [2]: foo()
455 In [2]: foo()
457 foo() was defined in an editing session
456 foo() was defined in an editing session
458
457
459 Now we edit foo. IPython automatically loads the editor with the
458 Now we edit foo. IPython automatically loads the editor with the
460 (temporary) file where foo() was previously defined::
459 (temporary) file where foo() was previously defined::
461
460
462 In [3]: edit foo
461 In [3]: edit foo
463 Editing... done. Executing edited code...
462 Editing... done. Executing edited code...
464
463
465 And if we call foo() again we get the modified version::
464 And if we call foo() again we get the modified version::
466
465
467 In [4]: foo()
466 In [4]: foo()
468 foo() has now been changed!
467 foo() has now been changed!
469
468
470 Here is an example of how to edit a code snippet successive
469 Here is an example of how to edit a code snippet successive
471 times. First we call the editor::
470 times. First we call the editor::
472
471
473 In [5]: edit
472 In [5]: edit
474 Editing... done. Executing edited code...
473 Editing... done. Executing edited code...
475 hello
474 hello
476 Out[5]: "print 'hello'\\n"
475 Out[5]: "print 'hello'\\n"
477
476
478 Now we call it again with the previous output (stored in _)::
477 Now we call it again with the previous output (stored in _)::
479
478
480 In [6]: edit _
479 In [6]: edit _
481 Editing... done. Executing edited code...
480 Editing... done. Executing edited code...
482 hello world
481 hello world
483 Out[6]: "print 'hello world'\\n"
482 Out[6]: "print 'hello world'\\n"
484
483
485 Now we call it with the output #8 (stored in _8, also as Out[8])::
484 Now we call it with the output #8 (stored in _8, also as Out[8])::
486
485
487 In [7]: edit _8
486 In [7]: edit _8
488 Editing... done. Executing edited code...
487 Editing... done. Executing edited code...
489 hello again
488 hello again
490 Out[7]: "print 'hello again'\\n"
489 Out[7]: "print 'hello again'\\n"
491
490
492
491
493 Changing the default editor hook:
492 Changing the default editor hook:
494
493
495 If you wish to write your own editor hook, you can put it in a
494 If you wish to write your own editor hook, you can put it in a
496 configuration file which you load at startup time. The default hook
495 configuration file which you load at startup time. The default hook
497 is defined in the IPython.core.hooks module, and you can use that as a
496 is defined in the IPython.core.hooks module, and you can use that as a
498 starting example for further modifications. That file also has
497 starting example for further modifications. That file also has
499 general instructions on how to set a new hook for use once you've
498 general instructions on how to set a new hook for use once you've
500 defined it."""
499 defined it."""
501 opts,args = self.parse_options(parameter_s,'prxn:')
500 opts,args = self.parse_options(parameter_s,'prxn:')
502
501
503 try:
502 try:
504 filename, lineno, is_temp = self._find_edit_target(self.shell,
503 filename, lineno, is_temp = self._find_edit_target(self.shell,
505 args, opts, last_call)
504 args, opts, last_call)
506 except MacroToEdit as e:
505 except MacroToEdit as e:
507 self._edit_macro(args, e.args[0])
506 self._edit_macro(args, e.args[0])
508 return
507 return
509 except InteractivelyDefined as e:
508 except InteractivelyDefined as e:
510 print "Editing In[%i]" % e.index
509 print "Editing In[%i]" % e.index
511 args = str(e.index)
510 args = str(e.index)
512 filename, lineno, is_temp = self._find_edit_target(self.shell,
511 filename, lineno, is_temp = self._find_edit_target(self.shell,
513 args, opts, last_call)
512 args, opts, last_call)
514 if filename is None:
513 if filename is None:
515 # nothing was found, warnings have already been issued,
514 # nothing was found, warnings have already been issued,
516 # just give up.
515 # just give up.
517 return
516 return
518
517
519 # do actual editing here
518 # do actual editing here
520 print 'Editing...',
519 print 'Editing...',
521 sys.stdout.flush()
520 sys.stdout.flush()
522 try:
521 try:
523 # Quote filenames that may have spaces in them
522 # Quote filenames that may have spaces in them
524 if ' ' in filename:
523 if ' ' in filename:
525 filename = "'%s'" % filename
524 filename = "'%s'" % filename
526 self.shell.hooks.editor(filename,lineno)
525 self.shell.hooks.editor(filename,lineno)
527 except TryNext:
526 except TryNext:
528 warn('Could not open editor')
527 warn('Could not open editor')
529 return
528 return
530
529
531 # XXX TODO: should this be generalized for all string vars?
530 # XXX TODO: should this be generalized for all string vars?
532 # For now, this is special-cased to blocks created by cpaste
531 # For now, this is special-cased to blocks created by cpaste
533 if args.strip() == 'pasted_block':
532 if args.strip() == 'pasted_block':
534 self.shell.user_ns['pasted_block'] = file_read(filename)
533 with open(filename, 'r') as f:
534 self.shell.user_ns['pasted_block'] = f.read()
535
535
536 if 'x' in opts: # -x prevents actual execution
536 if 'x' in opts: # -x prevents actual execution
537 print
537 print
538 else:
538 else:
539 print 'done. Executing edited code...'
539 print 'done. Executing edited code...'
540 with preserve_keys(self.shell.user_ns, '__file__'):
540 with preserve_keys(self.shell.user_ns, '__file__'):
541 if not is_temp:
541 if not is_temp:
542 self.shell.user_ns['__file__'] = filename
542 self.shell.user_ns['__file__'] = filename
543 if 'r' in opts: # Untranslated IPython code
543 if 'r' in opts: # Untranslated IPython code
544 self.shell.run_cell(file_read(filename),
544 with open(filename, 'r') as f:
545 store_history=False)
545 source = f.read()
546 self.shell.run_cell(source, store_history=False)
546 else:
547 else:
547 self.shell.safe_execfile(filename, self.shell.user_ns,
548 self.shell.safe_execfile(filename, self.shell.user_ns,
548 self.shell.user_ns)
549 self.shell.user_ns)
549
550
550 if is_temp:
551 if is_temp:
551 try:
552 try:
552 return open(filename).read()
553 return open(filename).read()
553 except IOError as msg:
554 except IOError as msg:
554 if msg.filename == filename:
555 if msg.filename == filename:
555 warn('File not found. Did you forget to save?')
556 warn('File not found. Did you forget to save?')
556 return
557 return
557 else:
558 else:
558 self.shell.showtraceback()
559 self.shell.showtraceback()
@@ -1,582 +1,582 b''
1 """Module for interactive demos using IPython.
1 """Module for interactive demos using IPython.
2
2
3 This module implements a few classes for running Python scripts interactively
3 This module implements a few classes for running Python scripts interactively
4 in IPython for demonstrations. With very simple markup (a few tags in
4 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
8
9 Provided classes
9 Provided classes
10 ----------------
10 ----------------
11
11
12 The classes are (see their docstrings for further details):
12 The classes are (see their docstrings for further details):
13
13
14 - Demo: pure python demos
14 - Demo: pure python demos
15
15
16 - IPythonDemo: demos with input to be processed by IPython as if it had been
16 - IPythonDemo: demos with input to be processed by IPython as if it had been
17 typed interactively (so magics work, as well as any other special syntax you
17 typed interactively (so magics work, as well as any other special syntax you
18 may have added via input prefilters).
18 may have added via input prefilters).
19
19
20 - LineDemo: single-line version of the Demo class. These demos are executed
20 - LineDemo: single-line version of the Demo class. These demos are executed
21 one line at a time, and require no markup.
21 one line at a time, and require no markup.
22
22
23 - IPythonLineDemo: IPython version of the LineDemo class (the demo is
23 - IPythonLineDemo: IPython version of the LineDemo class (the demo is
24 executed a line at a time, but processed via IPython).
24 executed a line at a time, but processed via IPython).
25
25
26 - ClearMixin: mixin to make Demo classes with less visual clutter. It
26 - ClearMixin: mixin to make Demo classes with less visual clutter. It
27 declares an empty marquee and a pre_cmd that clears the screen before each
27 declares an empty marquee and a pre_cmd that clears the screen before each
28 block (see Subclassing below).
28 block (see Subclassing below).
29
29
30 - ClearDemo, ClearIPDemo: mixin-enabled versions of the Demo and IPythonDemo
30 - ClearDemo, ClearIPDemo: mixin-enabled versions of the Demo and IPythonDemo
31 classes.
31 classes.
32
32
33 Inheritance diagram:
33 Inheritance diagram:
34
34
35 .. inheritance-diagram:: IPython.lib.demo
35 .. inheritance-diagram:: IPython.lib.demo
36 :parts: 3
36 :parts: 3
37
37
38 Subclassing
38 Subclassing
39 -----------
39 -----------
40
40
41 The classes here all include a few methods meant to make customization by
41 The classes here all include a few methods meant to make customization by
42 subclassing more convenient. Their docstrings below have some more details:
42 subclassing more convenient. Their docstrings below have some more details:
43
43
44 - marquee(): generates a marquee to provide visible on-screen markers at each
44 - marquee(): generates a marquee to provide visible on-screen markers at each
45 block start and end.
45 block start and end.
46
46
47 - pre_cmd(): run right before the execution of each block.
47 - pre_cmd(): run right before the execution of each block.
48
48
49 - post_cmd(): run right after the execution of each block. If the block
49 - post_cmd(): run right after the execution of each block. If the block
50 raises an exception, this is NOT called.
50 raises an exception, this is NOT called.
51
51
52
52
53 Operation
53 Operation
54 ---------
54 ---------
55
55
56 The file is run in its own empty namespace (though you can pass it a string of
56 The file is run in its own empty namespace (though you can pass it a string of
57 arguments as if in a command line environment, and it will see those as
57 arguments as if in a command line environment, and it will see those as
58 sys.argv). But at each stop, the global IPython namespace is updated with the
58 sys.argv). But at each stop, the global IPython namespace is updated with the
59 current internal demo namespace, so you can work interactively with the data
59 current internal demo namespace, so you can work interactively with the data
60 accumulated so far.
60 accumulated so far.
61
61
62 By default, each block of code is printed (with syntax highlighting) before
62 By default, each block of code is printed (with syntax highlighting) before
63 executing it and you have to confirm execution. This is intended to show the
63 executing it and you have to confirm execution. This is intended to show the
64 code to an audience first so you can discuss it, and only proceed with
64 code to an audience first so you can discuss it, and only proceed with
65 execution once you agree. There are a few tags which allow you to modify this
65 execution once you agree. There are a few tags which allow you to modify this
66 behavior.
66 behavior.
67
67
68 The supported tags are:
68 The supported tags are:
69
69
70 # <demo> stop
70 # <demo> stop
71
71
72 Defines block boundaries, the points where IPython stops execution of the
72 Defines block boundaries, the points where IPython stops execution of the
73 file and returns to the interactive prompt.
73 file and returns to the interactive prompt.
74
74
75 You can optionally mark the stop tag with extra dashes before and after the
75 You can optionally mark the stop tag with extra dashes before and after the
76 word 'stop', to help visually distinguish the blocks in a text editor:
76 word 'stop', to help visually distinguish the blocks in a text editor:
77
77
78 # <demo> --- stop ---
78 # <demo> --- stop ---
79
79
80
80
81 # <demo> silent
81 # <demo> silent
82
82
83 Make a block execute silently (and hence automatically). Typically used in
83 Make a block execute silently (and hence automatically). Typically used in
84 cases where you have some boilerplate or initialization code which you need
84 cases where you have some boilerplate or initialization code which you need
85 executed but do not want to be seen in the demo.
85 executed but do not want to be seen in the demo.
86
86
87 # <demo> auto
87 # <demo> auto
88
88
89 Make a block execute automatically, but still being printed. Useful for
89 Make a block execute automatically, but still being printed. Useful for
90 simple code which does not warrant discussion, since it avoids the extra
90 simple code which does not warrant discussion, since it avoids the extra
91 manual confirmation.
91 manual confirmation.
92
92
93 # <demo> auto_all
93 # <demo> auto_all
94
94
95 This tag can _only_ be in the first block, and if given it overrides the
95 This tag can _only_ be in the first block, and if given it overrides the
96 individual auto tags to make the whole demo fully automatic (no block asks
96 individual auto tags to make the whole demo fully automatic (no block asks
97 for confirmation). It can also be given at creation time (or the attribute
97 for confirmation). It can also be given at creation time (or the attribute
98 set later) to override what's in the file.
98 set later) to override what's in the file.
99
99
100 While _any_ python file can be run as a Demo instance, if there are no stop
100 While _any_ python file can be run as a Demo instance, if there are no stop
101 tags the whole file will run in a single block (no different that calling
101 tags the whole file will run in a single block (no different that calling
102 first %pycat and then %run). The minimal markup to make this useful is to
102 first %pycat and then %run). The minimal markup to make this useful is to
103 place a set of stop tags; the other tags are only there to let you fine-tune
103 place a set of stop tags; the other tags are only there to let you fine-tune
104 the execution.
104 the execution.
105
105
106 This is probably best explained with the simple example file below. You can
106 This is probably best explained with the simple example file below. You can
107 copy this into a file named ex_demo.py, and try running it via::
107 copy this into a file named ex_demo.py, and try running it via::
108
108
109 from IPython.demo import Demo
109 from IPython.demo import Demo
110 d = Demo('ex_demo.py')
110 d = Demo('ex_demo.py')
111 d()
111 d()
112
112
113 Each time you call the demo object, it runs the next block. The demo object
113 Each time you call the demo object, it runs the next block. The demo object
114 has a few useful methods for navigation, like again(), edit(), jump(), seek()
114 has a few useful methods for navigation, like again(), edit(), jump(), seek()
115 and back(). It can be reset for a new run via reset() or reloaded from disk
115 and back(). It can be reset for a new run via reset() or reloaded from disk
116 (in case you've edited the source) via reload(). See their docstrings below.
116 (in case you've edited the source) via reload(). See their docstrings below.
117
117
118 Note: To make this simpler to explore, a file called "demo-exercizer.py" has
118 Note: To make this simpler to explore, a file called "demo-exercizer.py" has
119 been added to the "docs/examples/core" directory. Just cd to this directory in
119 been added to the "docs/examples/core" directory. Just cd to this directory in
120 an IPython session, and type::
120 an IPython session, and type::
121
121
122 %run demo-exercizer.py
122 %run demo-exercizer.py
123
123
124 and then follow the directions.
124 and then follow the directions.
125
125
126 Example
126 Example
127 -------
127 -------
128
128
129 The following is a very simple example of a valid demo file.
129 The following is a very simple example of a valid demo file.
130
130
131 ::
131 ::
132
132
133 #################### EXAMPLE DEMO <ex_demo.py> ###############################
133 #################### EXAMPLE DEMO <ex_demo.py> ###############################
134 '''A simple interactive demo to illustrate the use of IPython's Demo class.'''
134 '''A simple interactive demo to illustrate the use of IPython's Demo class.'''
135
135
136 print 'Hello, welcome to an interactive IPython demo.'
136 print 'Hello, welcome to an interactive IPython demo.'
137
137
138 # The mark below defines a block boundary, which is a point where IPython will
138 # The mark below defines a block boundary, which is a point where IPython will
139 # stop execution and return to the interactive prompt. The dashes are actually
139 # stop execution and return to the interactive prompt. The dashes are actually
140 # optional and used only as a visual aid to clearly separate blocks while
140 # optional and used only as a visual aid to clearly separate blocks while
141 # editing the demo code.
141 # editing the demo code.
142 # <demo> stop
142 # <demo> stop
143
143
144 x = 1
144 x = 1
145 y = 2
145 y = 2
146
146
147 # <demo> stop
147 # <demo> stop
148
148
149 # the mark below makes this block as silent
149 # the mark below makes this block as silent
150 # <demo> silent
150 # <demo> silent
151
151
152 print 'This is a silent block, which gets executed but not printed.'
152 print 'This is a silent block, which gets executed but not printed.'
153
153
154 # <demo> stop
154 # <demo> stop
155 # <demo> auto
155 # <demo> auto
156 print 'This is an automatic block.'
156 print 'This is an automatic block.'
157 print 'It is executed without asking for confirmation, but printed.'
157 print 'It is executed without asking for confirmation, but printed.'
158 z = x+y
158 z = x+y
159
159
160 print 'z=',x
160 print 'z=',x
161
161
162 # <demo> stop
162 # <demo> stop
163 # This is just another normal block.
163 # This is just another normal block.
164 print 'z is now:', z
164 print 'z is now:', z
165
165
166 print 'bye!'
166 print 'bye!'
167 ################### END EXAMPLE DEMO <ex_demo.py> ############################
167 ################### END EXAMPLE DEMO <ex_demo.py> ############################
168 """
168 """
169
169
170 from __future__ import unicode_literals
170 from __future__ import unicode_literals
171
171
172 #*****************************************************************************
172 #*****************************************************************************
173 # Copyright (C) 2005-2006 Fernando Perez. <Fernando.Perez@colorado.edu>
173 # Copyright (C) 2005-2006 Fernando Perez. <Fernando.Perez@colorado.edu>
174 #
174 #
175 # Distributed under the terms of the BSD License. The full license is in
175 # Distributed under the terms of the BSD License. The full license is in
176 # the file COPYING, distributed as part of this software.
176 # the file COPYING, distributed as part of this software.
177 #
177 #
178 #*****************************************************************************
178 #*****************************************************************************
179 from __future__ import print_function
179 from __future__ import print_function
180
180
181 import os
181 import os
182 import re
182 import re
183 import shlex
183 import shlex
184 import sys
184 import sys
185
185
186 from IPython.utils import io
186 from IPython.utils import io
187 from IPython.utils.io import file_read
188 from IPython.utils.text import marquee
187 from IPython.utils.text import marquee
189 from IPython.utils import openpy
188 from IPython.utils import openpy
190 __all__ = ['Demo','IPythonDemo','LineDemo','IPythonLineDemo','DemoError']
189 __all__ = ['Demo','IPythonDemo','LineDemo','IPythonLineDemo','DemoError']
191
190
192 class DemoError(Exception): pass
191 class DemoError(Exception): pass
193
192
194 def re_mark(mark):
193 def re_mark(mark):
195 return re.compile(r'^\s*#\s+<demo>\s+%s\s*$' % mark,re.MULTILINE)
194 return re.compile(r'^\s*#\s+<demo>\s+%s\s*$' % mark,re.MULTILINE)
196
195
197 class Demo(object):
196 class Demo(object):
198
197
199 re_stop = re_mark('-*\s?stop\s?-*')
198 re_stop = re_mark('-*\s?stop\s?-*')
200 re_silent = re_mark('silent')
199 re_silent = re_mark('silent')
201 re_auto = re_mark('auto')
200 re_auto = re_mark('auto')
202 re_auto_all = re_mark('auto_all')
201 re_auto_all = re_mark('auto_all')
203
202
204 def __init__(self,src,title='',arg_str='',auto_all=None):
203 def __init__(self,src,title='',arg_str='',auto_all=None):
205 """Make a new demo object. To run the demo, simply call the object.
204 """Make a new demo object. To run the demo, simply call the object.
206
205
207 See the module docstring for full details and an example (you can use
206 See the module docstring for full details and an example (you can use
208 IPython.Demo? in IPython to see it).
207 IPython.Demo? in IPython to see it).
209
208
210 Inputs:
209 Inputs:
211
210
212 - src is either a file, or file-like object, or a
211 - src is either a file, or file-like object, or a
213 string that can be resolved to a filename.
212 string that can be resolved to a filename.
214
213
215 Optional inputs:
214 Optional inputs:
216
215
217 - title: a string to use as the demo name. Of most use when the demo
216 - title: a string to use as the demo name. Of most use when the demo
218 you are making comes from an object that has no filename, or if you
217 you are making comes from an object that has no filename, or if you
219 want an alternate denotation distinct from the filename.
218 want an alternate denotation distinct from the filename.
220
219
221 - arg_str(''): a string of arguments, internally converted to a list
220 - arg_str(''): a string of arguments, internally converted to a list
222 just like sys.argv, so the demo script can see a similar
221 just like sys.argv, so the demo script can see a similar
223 environment.
222 environment.
224
223
225 - auto_all(None): global flag to run all blocks automatically without
224 - auto_all(None): global flag to run all blocks automatically without
226 confirmation. This attribute overrides the block-level tags and
225 confirmation. This attribute overrides the block-level tags and
227 applies to the whole demo. It is an attribute of the object, and
226 applies to the whole demo. It is an attribute of the object, and
228 can be changed at runtime simply by reassigning it to a boolean
227 can be changed at runtime simply by reassigning it to a boolean
229 value.
228 value.
230 """
229 """
231 if hasattr(src, "read"):
230 if hasattr(src, "read"):
232 # It seems to be a file or a file-like object
231 # It seems to be a file or a file-like object
233 self.fname = "from a file-like object"
232 self.fname = "from a file-like object"
234 if title == '':
233 if title == '':
235 self.title = "from a file-like object"
234 self.title = "from a file-like object"
236 else:
235 else:
237 self.title = title
236 self.title = title
238 else:
237 else:
239 # Assume it's a string or something that can be converted to one
238 # Assume it's a string or something that can be converted to one
240 self.fname = src
239 self.fname = src
241 if title == '':
240 if title == '':
242 (filepath, filename) = os.path.split(src)
241 (filepath, filename) = os.path.split(src)
243 self.title = filename
242 self.title = filename
244 else:
243 else:
245 self.title = title
244 self.title = title
246 self.sys_argv = [src] + shlex.split(arg_str)
245 self.sys_argv = [src] + shlex.split(arg_str)
247 self.auto_all = auto_all
246 self.auto_all = auto_all
248 self.src = src
247 self.src = src
249
248
250 # get a few things from ipython. While it's a bit ugly design-wise,
249 # get a few things from ipython. While it's a bit ugly design-wise,
251 # it ensures that things like color scheme and the like are always in
250 # it ensures that things like color scheme and the like are always in
252 # sync with the ipython mode being used. This class is only meant to
251 # sync with the ipython mode being used. This class is only meant to
253 # be used inside ipython anyways, so it's OK.
252 # be used inside ipython anyways, so it's OK.
254 ip = get_ipython() # this is in builtins whenever IPython is running
253 ip = get_ipython() # this is in builtins whenever IPython is running
255 self.ip_ns = ip.user_ns
254 self.ip_ns = ip.user_ns
256 self.ip_colorize = ip.pycolorize
255 self.ip_colorize = ip.pycolorize
257 self.ip_showtb = ip.showtraceback
256 self.ip_showtb = ip.showtraceback
258 self.ip_run_cell = ip.run_cell
257 self.ip_run_cell = ip.run_cell
259 self.shell = ip
258 self.shell = ip
260
259
261 # load user data and initialize data structures
260 # load user data and initialize data structures
262 self.reload()
261 self.reload()
263
262
264 def fload(self):
263 def fload(self):
265 """Load file object."""
264 """Load file object."""
266 # read data and parse into blocks
265 # read data and parse into blocks
267 if hasattr(self, 'fobj') and self.fobj is not None:
266 if hasattr(self, 'fobj') and self.fobj is not None:
268 self.fobj.close()
267 self.fobj.close()
269 if hasattr(self.src, "read"):
268 if hasattr(self.src, "read"):
270 # It seems to be a file or a file-like object
269 # It seems to be a file or a file-like object
271 self.fobj = self.src
270 self.fobj = self.src
272 else:
271 else:
273 # Assume it's a string or something that can be converted to one
272 # Assume it's a string or something that can be converted to one
274 self.fobj = openpy.open(self.fname)
273 self.fobj = openpy.open(self.fname)
275
274
276 def reload(self):
275 def reload(self):
277 """Reload source from disk and initialize state."""
276 """Reload source from disk and initialize state."""
278 self.fload()
277 self.fload()
279
278
280 self.src = "".join(openpy.strip_encoding_cookie(self.fobj))
279 self.src = "".join(openpy.strip_encoding_cookie(self.fobj))
281 src_b = [b.strip() for b in self.re_stop.split(self.src) if b]
280 src_b = [b.strip() for b in self.re_stop.split(self.src) if b]
282 self._silent = [bool(self.re_silent.findall(b)) for b in src_b]
281 self._silent = [bool(self.re_silent.findall(b)) for b in src_b]
283 self._auto = [bool(self.re_auto.findall(b)) for b in src_b]
282 self._auto = [bool(self.re_auto.findall(b)) for b in src_b]
284
283
285 # if auto_all is not given (def. None), we read it from the file
284 # if auto_all is not given (def. None), we read it from the file
286 if self.auto_all is None:
285 if self.auto_all is None:
287 self.auto_all = bool(self.re_auto_all.findall(src_b[0]))
286 self.auto_all = bool(self.re_auto_all.findall(src_b[0]))
288 else:
287 else:
289 self.auto_all = bool(self.auto_all)
288 self.auto_all = bool(self.auto_all)
290
289
291 # Clean the sources from all markup so it doesn't get displayed when
290 # Clean the sources from all markup so it doesn't get displayed when
292 # running the demo
291 # running the demo
293 src_blocks = []
292 src_blocks = []
294 auto_strip = lambda s: self.re_auto.sub('',s)
293 auto_strip = lambda s: self.re_auto.sub('',s)
295 for i,b in enumerate(src_b):
294 for i,b in enumerate(src_b):
296 if self._auto[i]:
295 if self._auto[i]:
297 src_blocks.append(auto_strip(b))
296 src_blocks.append(auto_strip(b))
298 else:
297 else:
299 src_blocks.append(b)
298 src_blocks.append(b)
300 # remove the auto_all marker
299 # remove the auto_all marker
301 src_blocks[0] = self.re_auto_all.sub('',src_blocks[0])
300 src_blocks[0] = self.re_auto_all.sub('',src_blocks[0])
302
301
303 self.nblocks = len(src_blocks)
302 self.nblocks = len(src_blocks)
304 self.src_blocks = src_blocks
303 self.src_blocks = src_blocks
305
304
306 # also build syntax-highlighted source
305 # also build syntax-highlighted source
307 self.src_blocks_colored = map(self.ip_colorize,self.src_blocks)
306 self.src_blocks_colored = map(self.ip_colorize,self.src_blocks)
308
307
309 # ensure clean namespace and seek offset
308 # ensure clean namespace and seek offset
310 self.reset()
309 self.reset()
311
310
312 def reset(self):
311 def reset(self):
313 """Reset the namespace and seek pointer to restart the demo"""
312 """Reset the namespace and seek pointer to restart the demo"""
314 self.user_ns = {}
313 self.user_ns = {}
315 self.finished = False
314 self.finished = False
316 self.block_index = 0
315 self.block_index = 0
317
316
318 def _validate_index(self,index):
317 def _validate_index(self,index):
319 if index<0 or index>=self.nblocks:
318 if index<0 or index>=self.nblocks:
320 raise ValueError('invalid block index %s' % index)
319 raise ValueError('invalid block index %s' % index)
321
320
322 def _get_index(self,index):
321 def _get_index(self,index):
323 """Get the current block index, validating and checking status.
322 """Get the current block index, validating and checking status.
324
323
325 Returns None if the demo is finished"""
324 Returns None if the demo is finished"""
326
325
327 if index is None:
326 if index is None:
328 if self.finished:
327 if self.finished:
329 print('Demo finished. Use <demo_name>.reset() if you want to rerun it.', file=io.stdout)
328 print('Demo finished. Use <demo_name>.reset() if you want to rerun it.', file=io.stdout)
330 return None
329 return None
331 index = self.block_index
330 index = self.block_index
332 else:
331 else:
333 self._validate_index(index)
332 self._validate_index(index)
334 return index
333 return index
335
334
336 def seek(self,index):
335 def seek(self,index):
337 """Move the current seek pointer to the given block.
336 """Move the current seek pointer to the given block.
338
337
339 You can use negative indices to seek from the end, with identical
338 You can use negative indices to seek from the end, with identical
340 semantics to those of Python lists."""
339 semantics to those of Python lists."""
341 if index<0:
340 if index<0:
342 index = self.nblocks + index
341 index = self.nblocks + index
343 self._validate_index(index)
342 self._validate_index(index)
344 self.block_index = index
343 self.block_index = index
345 self.finished = False
344 self.finished = False
346
345
347 def back(self,num=1):
346 def back(self,num=1):
348 """Move the seek pointer back num blocks (default is 1)."""
347 """Move the seek pointer back num blocks (default is 1)."""
349 self.seek(self.block_index-num)
348 self.seek(self.block_index-num)
350
349
351 def jump(self,num=1):
350 def jump(self,num=1):
352 """Jump a given number of blocks relative to the current one.
351 """Jump a given number of blocks relative to the current one.
353
352
354 The offset can be positive or negative, defaults to 1."""
353 The offset can be positive or negative, defaults to 1."""
355 self.seek(self.block_index+num)
354 self.seek(self.block_index+num)
356
355
357 def again(self):
356 def again(self):
358 """Move the seek pointer back one block and re-execute."""
357 """Move the seek pointer back one block and re-execute."""
359 self.back(1)
358 self.back(1)
360 self()
359 self()
361
360
362 def edit(self,index=None):
361 def edit(self,index=None):
363 """Edit a block.
362 """Edit a block.
364
363
365 If no number is given, use the last block executed.
364 If no number is given, use the last block executed.
366
365
367 This edits the in-memory copy of the demo, it does NOT modify the
366 This edits the in-memory copy of the demo, it does NOT modify the
368 original source file. If you want to do that, simply open the file in
367 original source file. If you want to do that, simply open the file in
369 an editor and use reload() when you make changes to the file. This
368 an editor and use reload() when you make changes to the file. This
370 method is meant to let you change a block during a demonstration for
369 method is meant to let you change a block during a demonstration for
371 explanatory purposes, without damaging your original script."""
370 explanatory purposes, without damaging your original script."""
372
371
373 index = self._get_index(index)
372 index = self._get_index(index)
374 if index is None:
373 if index is None:
375 return
374 return
376 # decrease the index by one (unless we're at the very beginning), so
375 # decrease the index by one (unless we're at the very beginning), so
377 # that the default demo.edit() call opens up the sblock we've last run
376 # that the default demo.edit() call opens up the sblock we've last run
378 if index>0:
377 if index>0:
379 index -= 1
378 index -= 1
380
379
381 filename = self.shell.mktempfile(self.src_blocks[index])
380 filename = self.shell.mktempfile(self.src_blocks[index])
382 self.shell.hooks.editor(filename,1)
381 self.shell.hooks.editor(filename,1)
383 new_block = file_read(filename)
382 with open(filename, 'r') as f:
383 new_block = f.read()
384 # update the source and colored block
384 # update the source and colored block
385 self.src_blocks[index] = new_block
385 self.src_blocks[index] = new_block
386 self.src_blocks_colored[index] = self.ip_colorize(new_block)
386 self.src_blocks_colored[index] = self.ip_colorize(new_block)
387 self.block_index = index
387 self.block_index = index
388 # call to run with the newly edited index
388 # call to run with the newly edited index
389 self()
389 self()
390
390
391 def show(self,index=None):
391 def show(self,index=None):
392 """Show a single block on screen"""
392 """Show a single block on screen"""
393
393
394 index = self._get_index(index)
394 index = self._get_index(index)
395 if index is None:
395 if index is None:
396 return
396 return
397
397
398 print(self.marquee('<%s> block # %s (%s remaining)' %
398 print(self.marquee('<%s> block # %s (%s remaining)' %
399 (self.title,index,self.nblocks-index-1)), file=io.stdout)
399 (self.title,index,self.nblocks-index-1)), file=io.stdout)
400 print((self.src_blocks_colored[index]), file=io.stdout)
400 print((self.src_blocks_colored[index]), file=io.stdout)
401 sys.stdout.flush()
401 sys.stdout.flush()
402
402
403 def show_all(self):
403 def show_all(self):
404 """Show entire demo on screen, block by block"""
404 """Show entire demo on screen, block by block"""
405
405
406 fname = self.title
406 fname = self.title
407 title = self.title
407 title = self.title
408 nblocks = self.nblocks
408 nblocks = self.nblocks
409 silent = self._silent
409 silent = self._silent
410 marquee = self.marquee
410 marquee = self.marquee
411 for index,block in enumerate(self.src_blocks_colored):
411 for index,block in enumerate(self.src_blocks_colored):
412 if silent[index]:
412 if silent[index]:
413 print(marquee('<%s> SILENT block # %s (%s remaining)' %
413 print(marquee('<%s> SILENT block # %s (%s remaining)' %
414 (title,index,nblocks-index-1)), file=io.stdout)
414 (title,index,nblocks-index-1)), file=io.stdout)
415 else:
415 else:
416 print(marquee('<%s> block # %s (%s remaining)' %
416 print(marquee('<%s> block # %s (%s remaining)' %
417 (title,index,nblocks-index-1)), file=io.stdout)
417 (title,index,nblocks-index-1)), file=io.stdout)
418 print(block, end=' ', file=io.stdout)
418 print(block, end=' ', file=io.stdout)
419 sys.stdout.flush()
419 sys.stdout.flush()
420
420
421 def run_cell(self,source):
421 def run_cell(self,source):
422 """Execute a string with one or more lines of code"""
422 """Execute a string with one or more lines of code"""
423
423
424 exec source in self.user_ns
424 exec source in self.user_ns
425
425
426 def __call__(self,index=None):
426 def __call__(self,index=None):
427 """run a block of the demo.
427 """run a block of the demo.
428
428
429 If index is given, it should be an integer >=1 and <= nblocks. This
429 If index is given, it should be an integer >=1 and <= nblocks. This
430 means that the calling convention is one off from typical Python
430 means that the calling convention is one off from typical Python
431 lists. The reason for the inconsistency is that the demo always
431 lists. The reason for the inconsistency is that the demo always
432 prints 'Block n/N, and N is the total, so it would be very odd to use
432 prints 'Block n/N, and N is the total, so it would be very odd to use
433 zero-indexing here."""
433 zero-indexing here."""
434
434
435 index = self._get_index(index)
435 index = self._get_index(index)
436 if index is None:
436 if index is None:
437 return
437 return
438 try:
438 try:
439 marquee = self.marquee
439 marquee = self.marquee
440 next_block = self.src_blocks[index]
440 next_block = self.src_blocks[index]
441 self.block_index += 1
441 self.block_index += 1
442 if self._silent[index]:
442 if self._silent[index]:
443 print(marquee('Executing silent block # %s (%s remaining)' %
443 print(marquee('Executing silent block # %s (%s remaining)' %
444 (index,self.nblocks-index-1)), file=io.stdout)
444 (index,self.nblocks-index-1)), file=io.stdout)
445 else:
445 else:
446 self.pre_cmd()
446 self.pre_cmd()
447 self.show(index)
447 self.show(index)
448 if self.auto_all or self._auto[index]:
448 if self.auto_all or self._auto[index]:
449 print(marquee('output:'), file=io.stdout)
449 print(marquee('output:'), file=io.stdout)
450 else:
450 else:
451 print(marquee('Press <q> to quit, <Enter> to execute...'), end=' ', file=io.stdout)
451 print(marquee('Press <q> to quit, <Enter> to execute...'), end=' ', file=io.stdout)
452 ans = raw_input().strip()
452 ans = raw_input().strip()
453 if ans:
453 if ans:
454 print(marquee('Block NOT executed'), file=io.stdout)
454 print(marquee('Block NOT executed'), file=io.stdout)
455 return
455 return
456 try:
456 try:
457 save_argv = sys.argv
457 save_argv = sys.argv
458 sys.argv = self.sys_argv
458 sys.argv = self.sys_argv
459 self.run_cell(next_block)
459 self.run_cell(next_block)
460 self.post_cmd()
460 self.post_cmd()
461 finally:
461 finally:
462 sys.argv = save_argv
462 sys.argv = save_argv
463
463
464 except:
464 except:
465 self.ip_showtb(filename=self.fname)
465 self.ip_showtb(filename=self.fname)
466 else:
466 else:
467 self.ip_ns.update(self.user_ns)
467 self.ip_ns.update(self.user_ns)
468
468
469 if self.block_index == self.nblocks:
469 if self.block_index == self.nblocks:
470 mq1 = self.marquee('END OF DEMO')
470 mq1 = self.marquee('END OF DEMO')
471 if mq1:
471 if mq1:
472 # avoid spurious print >>io.stdout,s if empty marquees are used
472 # avoid spurious print >>io.stdout,s if empty marquees are used
473 print(file=io.stdout)
473 print(file=io.stdout)
474 print(mq1, file=io.stdout)
474 print(mq1, file=io.stdout)
475 print(self.marquee('Use <demo_name>.reset() if you want to rerun it.'), file=io.stdout)
475 print(self.marquee('Use <demo_name>.reset() if you want to rerun it.'), file=io.stdout)
476 self.finished = True
476 self.finished = True
477
477
478 # These methods are meant to be overridden by subclasses who may wish to
478 # These methods are meant to be overridden by subclasses who may wish to
479 # customize the behavior of of their demos.
479 # customize the behavior of of their demos.
480 def marquee(self,txt='',width=78,mark='*'):
480 def marquee(self,txt='',width=78,mark='*'):
481 """Return the input string centered in a 'marquee'."""
481 """Return the input string centered in a 'marquee'."""
482 return marquee(txt,width,mark)
482 return marquee(txt,width,mark)
483
483
484 def pre_cmd(self):
484 def pre_cmd(self):
485 """Method called before executing each block."""
485 """Method called before executing each block."""
486 pass
486 pass
487
487
488 def post_cmd(self):
488 def post_cmd(self):
489 """Method called after executing each block."""
489 """Method called after executing each block."""
490 pass
490 pass
491
491
492
492
493 class IPythonDemo(Demo):
493 class IPythonDemo(Demo):
494 """Class for interactive demos with IPython's input processing applied.
494 """Class for interactive demos with IPython's input processing applied.
495
495
496 This subclasses Demo, but instead of executing each block by the Python
496 This subclasses Demo, but instead of executing each block by the Python
497 interpreter (via exec), it actually calls IPython on it, so that any input
497 interpreter (via exec), it actually calls IPython on it, so that any input
498 filters which may be in place are applied to the input block.
498 filters which may be in place are applied to the input block.
499
499
500 If you have an interactive environment which exposes special input
500 If you have an interactive environment which exposes special input
501 processing, you can use this class instead to write demo scripts which
501 processing, you can use this class instead to write demo scripts which
502 operate exactly as if you had typed them interactively. The default Demo
502 operate exactly as if you had typed them interactively. The default Demo
503 class requires the input to be valid, pure Python code.
503 class requires the input to be valid, pure Python code.
504 """
504 """
505
505
506 def run_cell(self,source):
506 def run_cell(self,source):
507 """Execute a string with one or more lines of code"""
507 """Execute a string with one or more lines of code"""
508
508
509 self.shell.run_cell(source)
509 self.shell.run_cell(source)
510
510
511 class LineDemo(Demo):
511 class LineDemo(Demo):
512 """Demo where each line is executed as a separate block.
512 """Demo where each line is executed as a separate block.
513
513
514 The input script should be valid Python code.
514 The input script should be valid Python code.
515
515
516 This class doesn't require any markup at all, and it's meant for simple
516 This class doesn't require any markup at all, and it's meant for simple
517 scripts (with no nesting or any kind of indentation) which consist of
517 scripts (with no nesting or any kind of indentation) which consist of
518 multiple lines of input to be executed, one at a time, as if they had been
518 multiple lines of input to be executed, one at a time, as if they had been
519 typed in the interactive prompt.
519 typed in the interactive prompt.
520
520
521 Note: the input can not have *any* indentation, which means that only
521 Note: the input can not have *any* indentation, which means that only
522 single-lines of input are accepted, not even function definitions are
522 single-lines of input are accepted, not even function definitions are
523 valid."""
523 valid."""
524
524
525 def reload(self):
525 def reload(self):
526 """Reload source from disk and initialize state."""
526 """Reload source from disk and initialize state."""
527 # read data and parse into blocks
527 # read data and parse into blocks
528 self.fload()
528 self.fload()
529 lines = self.fobj.readlines()
529 lines = self.fobj.readlines()
530 src_b = [l for l in lines if l.strip()]
530 src_b = [l for l in lines if l.strip()]
531 nblocks = len(src_b)
531 nblocks = len(src_b)
532 self.src = ''.join(lines)
532 self.src = ''.join(lines)
533 self._silent = [False]*nblocks
533 self._silent = [False]*nblocks
534 self._auto = [True]*nblocks
534 self._auto = [True]*nblocks
535 self.auto_all = True
535 self.auto_all = True
536 self.nblocks = nblocks
536 self.nblocks = nblocks
537 self.src_blocks = src_b
537 self.src_blocks = src_b
538
538
539 # also build syntax-highlighted source
539 # also build syntax-highlighted source
540 self.src_blocks_colored = map(self.ip_colorize,self.src_blocks)
540 self.src_blocks_colored = map(self.ip_colorize,self.src_blocks)
541
541
542 # ensure clean namespace and seek offset
542 # ensure clean namespace and seek offset
543 self.reset()
543 self.reset()
544
544
545
545
546 class IPythonLineDemo(IPythonDemo,LineDemo):
546 class IPythonLineDemo(IPythonDemo,LineDemo):
547 """Variant of the LineDemo class whose input is processed by IPython."""
547 """Variant of the LineDemo class whose input is processed by IPython."""
548 pass
548 pass
549
549
550
550
551 class ClearMixin(object):
551 class ClearMixin(object):
552 """Use this mixin to make Demo classes with less visual clutter.
552 """Use this mixin to make Demo classes with less visual clutter.
553
553
554 Demos using this mixin will clear the screen before every block and use
554 Demos using this mixin will clear the screen before every block and use
555 blank marquees.
555 blank marquees.
556
556
557 Note that in order for the methods defined here to actually override those
557 Note that in order for the methods defined here to actually override those
558 of the classes it's mixed with, it must go /first/ in the inheritance
558 of the classes it's mixed with, it must go /first/ in the inheritance
559 tree. For example:
559 tree. For example:
560
560
561 class ClearIPDemo(ClearMixin,IPythonDemo): pass
561 class ClearIPDemo(ClearMixin,IPythonDemo): pass
562
562
563 will provide an IPythonDemo class with the mixin's features.
563 will provide an IPythonDemo class with the mixin's features.
564 """
564 """
565
565
566 def marquee(self,txt='',width=78,mark='*'):
566 def marquee(self,txt='',width=78,mark='*'):
567 """Blank marquee that returns '' no matter what the input."""
567 """Blank marquee that returns '' no matter what the input."""
568 return ''
568 return ''
569
569
570 def pre_cmd(self):
570 def pre_cmd(self):
571 """Method called before executing each block.
571 """Method called before executing each block.
572
572
573 This one simply clears the screen."""
573 This one simply clears the screen."""
574 from IPython.utils.terminal import term_clear
574 from IPython.utils.terminal import term_clear
575 term_clear()
575 term_clear()
576
576
577 class ClearDemo(ClearMixin,Demo):
577 class ClearDemo(ClearMixin,Demo):
578 pass
578 pass
579
579
580
580
581 class ClearIPDemo(ClearMixin,IPythonDemo):
581 class ClearIPDemo(ClearMixin,IPythonDemo):
582 pass
582 pass
@@ -1,346 +1,330 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 IO related utilities.
3 IO related utilities.
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2008-2011 The IPython Development Team
7 # Copyright (C) 2008-2011 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 from __future__ import print_function
12 from __future__ import print_function
13
13
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 import os
17 import os
18 import sys
18 import sys
19 import tempfile
19 import tempfile
20 from StringIO import StringIO
20 from StringIO import StringIO
21
21
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23 # Code
23 # Code
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25
25
26
26
27 class IOStream:
27 class IOStream:
28
28
29 def __init__(self,stream, fallback=None):
29 def __init__(self,stream, fallback=None):
30 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
30 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
31 if fallback is not None:
31 if fallback is not None:
32 stream = fallback
32 stream = fallback
33 else:
33 else:
34 raise ValueError("fallback required, but not specified")
34 raise ValueError("fallback required, but not specified")
35 self.stream = stream
35 self.stream = stream
36 self._swrite = stream.write
36 self._swrite = stream.write
37
37
38 # clone all methods not overridden:
38 # clone all methods not overridden:
39 def clone(meth):
39 def clone(meth):
40 return not hasattr(self, meth) and not meth.startswith('_')
40 return not hasattr(self, meth) and not meth.startswith('_')
41 for meth in filter(clone, dir(stream)):
41 for meth in filter(clone, dir(stream)):
42 setattr(self, meth, getattr(stream, meth))
42 setattr(self, meth, getattr(stream, meth))
43
43
44 def write(self,data):
44 def write(self,data):
45 try:
45 try:
46 self._swrite(data)
46 self._swrite(data)
47 except:
47 except:
48 try:
48 try:
49 # print handles some unicode issues which may trip a plain
49 # print handles some unicode issues which may trip a plain
50 # write() call. Emulate write() by using an empty end
50 # write() call. Emulate write() by using an empty end
51 # argument.
51 # argument.
52 print(data, end='', file=self.stream)
52 print(data, end='', file=self.stream)
53 except:
53 except:
54 # if we get here, something is seriously broken.
54 # if we get here, something is seriously broken.
55 print('ERROR - failed to write data to stream:', self.stream,
55 print('ERROR - failed to write data to stream:', self.stream,
56 file=sys.stderr)
56 file=sys.stderr)
57
57
58 def writelines(self, lines):
58 def writelines(self, lines):
59 if isinstance(lines, basestring):
59 if isinstance(lines, basestring):
60 lines = [lines]
60 lines = [lines]
61 for line in lines:
61 for line in lines:
62 self.write(line)
62 self.write(line)
63
63
64 # This class used to have a writeln method, but regular files and streams
64 # This class used to have a writeln method, but regular files and streams
65 # in Python don't have this method. We need to keep this completely
65 # in Python don't have this method. We need to keep this completely
66 # compatible so we removed it.
66 # compatible so we removed it.
67
67
68 @property
68 @property
69 def closed(self):
69 def closed(self):
70 return self.stream.closed
70 return self.stream.closed
71
71
72 def close(self):
72 def close(self):
73 pass
73 pass
74
74
75 # setup stdin/stdout/stderr to sys.stdin/sys.stdout/sys.stderr
75 # setup stdin/stdout/stderr to sys.stdin/sys.stdout/sys.stderr
76 devnull = open(os.devnull, 'a')
76 devnull = open(os.devnull, 'a')
77 stdin = IOStream(sys.stdin, fallback=devnull)
77 stdin = IOStream(sys.stdin, fallback=devnull)
78 stdout = IOStream(sys.stdout, fallback=devnull)
78 stdout = IOStream(sys.stdout, fallback=devnull)
79 stderr = IOStream(sys.stderr, fallback=devnull)
79 stderr = IOStream(sys.stderr, fallback=devnull)
80
80
81 class IOTerm:
81 class IOTerm:
82 """ Term holds the file or file-like objects for handling I/O operations.
82 """ Term holds the file or file-like objects for handling I/O operations.
83
83
84 These are normally just sys.stdin, sys.stdout and sys.stderr but for
84 These are normally just sys.stdin, sys.stdout and sys.stderr but for
85 Windows they can can replaced to allow editing the strings before they are
85 Windows they can can replaced to allow editing the strings before they are
86 displayed."""
86 displayed."""
87
87
88 # In the future, having IPython channel all its I/O operations through
88 # In the future, having IPython channel all its I/O operations through
89 # this class will make it easier to embed it into other environments which
89 # this class will make it easier to embed it into other environments which
90 # are not a normal terminal (such as a GUI-based shell)
90 # are not a normal terminal (such as a GUI-based shell)
91 def __init__(self, stdin=None, stdout=None, stderr=None):
91 def __init__(self, stdin=None, stdout=None, stderr=None):
92 mymodule = sys.modules[__name__]
92 mymodule = sys.modules[__name__]
93 self.stdin = IOStream(stdin, mymodule.stdin)
93 self.stdin = IOStream(stdin, mymodule.stdin)
94 self.stdout = IOStream(stdout, mymodule.stdout)
94 self.stdout = IOStream(stdout, mymodule.stdout)
95 self.stderr = IOStream(stderr, mymodule.stderr)
95 self.stderr = IOStream(stderr, mymodule.stderr)
96
96
97
97
98 class Tee(object):
98 class Tee(object):
99 """A class to duplicate an output stream to stdout/err.
99 """A class to duplicate an output stream to stdout/err.
100
100
101 This works in a manner very similar to the Unix 'tee' command.
101 This works in a manner very similar to the Unix 'tee' command.
102
102
103 When the object is closed or deleted, it closes the original file given to
103 When the object is closed or deleted, it closes the original file given to
104 it for duplication.
104 it for duplication.
105 """
105 """
106 # Inspired by:
106 # Inspired by:
107 # http://mail.python.org/pipermail/python-list/2007-May/442737.html
107 # http://mail.python.org/pipermail/python-list/2007-May/442737.html
108
108
109 def __init__(self, file_or_name, mode="w", channel='stdout'):
109 def __init__(self, file_or_name, mode="w", channel='stdout'):
110 """Construct a new Tee object.
110 """Construct a new Tee object.
111
111
112 Parameters
112 Parameters
113 ----------
113 ----------
114 file_or_name : filename or open filehandle (writable)
114 file_or_name : filename or open filehandle (writable)
115 File that will be duplicated
115 File that will be duplicated
116
116
117 mode : optional, valid mode for open().
117 mode : optional, valid mode for open().
118 If a filename was give, open with this mode.
118 If a filename was give, open with this mode.
119
119
120 channel : str, one of ['stdout', 'stderr']
120 channel : str, one of ['stdout', 'stderr']
121 """
121 """
122 if channel not in ['stdout', 'stderr']:
122 if channel not in ['stdout', 'stderr']:
123 raise ValueError('Invalid channel spec %s' % channel)
123 raise ValueError('Invalid channel spec %s' % channel)
124
124
125 if hasattr(file_or_name, 'write') and hasattr(file_or_name, 'seek'):
125 if hasattr(file_or_name, 'write') and hasattr(file_or_name, 'seek'):
126 self.file = file_or_name
126 self.file = file_or_name
127 else:
127 else:
128 self.file = open(file_or_name, mode)
128 self.file = open(file_or_name, mode)
129 self.channel = channel
129 self.channel = channel
130 self.ostream = getattr(sys, channel)
130 self.ostream = getattr(sys, channel)
131 setattr(sys, channel, self)
131 setattr(sys, channel, self)
132 self._closed = False
132 self._closed = False
133
133
134 def close(self):
134 def close(self):
135 """Close the file and restore the channel."""
135 """Close the file and restore the channel."""
136 self.flush()
136 self.flush()
137 setattr(sys, self.channel, self.ostream)
137 setattr(sys, self.channel, self.ostream)
138 self.file.close()
138 self.file.close()
139 self._closed = True
139 self._closed = True
140
140
141 def write(self, data):
141 def write(self, data):
142 """Write data to both channels."""
142 """Write data to both channels."""
143 self.file.write(data)
143 self.file.write(data)
144 self.ostream.write(data)
144 self.ostream.write(data)
145 self.ostream.flush()
145 self.ostream.flush()
146
146
147 def flush(self):
147 def flush(self):
148 """Flush both channels."""
148 """Flush both channels."""
149 self.file.flush()
149 self.file.flush()
150 self.ostream.flush()
150 self.ostream.flush()
151
151
152 def __del__(self):
152 def __del__(self):
153 if not self._closed:
153 if not self._closed:
154 self.close()
154 self.close()
155
155
156
156
157 def file_read(filename):
158 """Read a file and close it. Returns the file source."""
159 fobj = open(filename,'r');
160 source = fobj.read();
161 fobj.close()
162 return source
163
164
165 def file_readlines(filename):
166 """Read a file and close it. Returns the file source using readlines()."""
167 fobj = open(filename,'r');
168 lines = fobj.readlines();
169 fobj.close()
170 return lines
171
172
173 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
157 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
174 """Take multiple lines of input.
158 """Take multiple lines of input.
175
159
176 A list with each line of input as a separate element is returned when a
160 A list with each line of input as a separate element is returned when a
177 termination string is entered (defaults to a single '.'). Input can also
161 termination string is entered (defaults to a single '.'). Input can also
178 terminate via EOF (^D in Unix, ^Z-RET in Windows).
162 terminate via EOF (^D in Unix, ^Z-RET in Windows).
179
163
180 Lines of input which end in \\ are joined into single entries (and a
164 Lines of input which end in \\ are joined into single entries (and a
181 secondary continuation prompt is issued as long as the user terminates
165 secondary continuation prompt is issued as long as the user terminates
182 lines with \\). This allows entering very long strings which are still
166 lines with \\). This allows entering very long strings which are still
183 meant to be treated as single entities.
167 meant to be treated as single entities.
184 """
168 """
185
169
186 try:
170 try:
187 if header:
171 if header:
188 header += '\n'
172 header += '\n'
189 lines = [raw_input(header + ps1)]
173 lines = [raw_input(header + ps1)]
190 except EOFError:
174 except EOFError:
191 return []
175 return []
192 terminate = [terminate_str]
176 terminate = [terminate_str]
193 try:
177 try:
194 while lines[-1:] != terminate:
178 while lines[-1:] != terminate:
195 new_line = raw_input(ps1)
179 new_line = raw_input(ps1)
196 while new_line.endswith('\\'):
180 while new_line.endswith('\\'):
197 new_line = new_line[:-1] + raw_input(ps2)
181 new_line = new_line[:-1] + raw_input(ps2)
198 lines.append(new_line)
182 lines.append(new_line)
199
183
200 return lines[:-1] # don't return the termination command
184 return lines[:-1] # don't return the termination command
201 except EOFError:
185 except EOFError:
202 print()
186 print()
203 return lines
187 return lines
204
188
205
189
206 def raw_input_ext(prompt='', ps2='... '):
190 def raw_input_ext(prompt='', ps2='... '):
207 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
191 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
208
192
209 line = raw_input(prompt)
193 line = raw_input(prompt)
210 while line.endswith('\\'):
194 while line.endswith('\\'):
211 line = line[:-1] + raw_input(ps2)
195 line = line[:-1] + raw_input(ps2)
212 return line
196 return line
213
197
214
198
215 def ask_yes_no(prompt,default=None):
199 def ask_yes_no(prompt,default=None):
216 """Asks a question and returns a boolean (y/n) answer.
200 """Asks a question and returns a boolean (y/n) answer.
217
201
218 If default is given (one of 'y','n'), it is used if the user input is
202 If default is given (one of 'y','n'), it is used if the user input is
219 empty. Otherwise the question is repeated until an answer is given.
203 empty. Otherwise the question is repeated until an answer is given.
220
204
221 An EOF is treated as the default answer. If there is no default, an
205 An EOF is treated as the default answer. If there is no default, an
222 exception is raised to prevent infinite loops.
206 exception is raised to prevent infinite loops.
223
207
224 Valid answers are: y/yes/n/no (match is not case sensitive)."""
208 Valid answers are: y/yes/n/no (match is not case sensitive)."""
225
209
226 answers = {'y':True,'n':False,'yes':True,'no':False}
210 answers = {'y':True,'n':False,'yes':True,'no':False}
227 ans = None
211 ans = None
228 while ans not in answers.keys():
212 while ans not in answers.keys():
229 try:
213 try:
230 ans = raw_input(prompt+' ').lower()
214 ans = raw_input(prompt+' ').lower()
231 if not ans: # response was an empty string
215 if not ans: # response was an empty string
232 ans = default
216 ans = default
233 except KeyboardInterrupt:
217 except KeyboardInterrupt:
234 pass
218 pass
235 except EOFError:
219 except EOFError:
236 if default in answers.keys():
220 if default in answers.keys():
237 ans = default
221 ans = default
238 print()
222 print()
239 else:
223 else:
240 raise
224 raise
241
225
242 return answers[ans]
226 return answers[ans]
243
227
244
228
245 def temp_pyfile(src, ext='.py'):
229 def temp_pyfile(src, ext='.py'):
246 """Make a temporary python file, return filename and filehandle.
230 """Make a temporary python file, return filename and filehandle.
247
231
248 Parameters
232 Parameters
249 ----------
233 ----------
250 src : string or list of strings (no need for ending newlines if list)
234 src : string or list of strings (no need for ending newlines if list)
251 Source code to be written to the file.
235 Source code to be written to the file.
252
236
253 ext : optional, string
237 ext : optional, string
254 Extension for the generated file.
238 Extension for the generated file.
255
239
256 Returns
240 Returns
257 -------
241 -------
258 (filename, open filehandle)
242 (filename, open filehandle)
259 It is the caller's responsibility to close the open file and unlink it.
243 It is the caller's responsibility to close the open file and unlink it.
260 """
244 """
261 fname = tempfile.mkstemp(ext)[1]
245 fname = tempfile.mkstemp(ext)[1]
262 f = open(fname,'w')
246 f = open(fname,'w')
263 f.write(src)
247 f.write(src)
264 f.flush()
248 f.flush()
265 return fname, f
249 return fname, f
266
250
267
251
268 def raw_print(*args, **kw):
252 def raw_print(*args, **kw):
269 """Raw print to sys.__stdout__, otherwise identical interface to print()."""
253 """Raw print to sys.__stdout__, otherwise identical interface to print()."""
270
254
271 print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
255 print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
272 file=sys.__stdout__)
256 file=sys.__stdout__)
273 sys.__stdout__.flush()
257 sys.__stdout__.flush()
274
258
275
259
276 def raw_print_err(*args, **kw):
260 def raw_print_err(*args, **kw):
277 """Raw print to sys.__stderr__, otherwise identical interface to print()."""
261 """Raw print to sys.__stderr__, otherwise identical interface to print()."""
278
262
279 print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
263 print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
280 file=sys.__stderr__)
264 file=sys.__stderr__)
281 sys.__stderr__.flush()
265 sys.__stderr__.flush()
282
266
283
267
284 # Short aliases for quick debugging, do NOT use these in production code.
268 # Short aliases for quick debugging, do NOT use these in production code.
285 rprint = raw_print
269 rprint = raw_print
286 rprinte = raw_print_err
270 rprinte = raw_print_err
287
271
288
272
289 class CapturedIO(object):
273 class CapturedIO(object):
290 """Simple object for containing captured stdout/err StringIO objects"""
274 """Simple object for containing captured stdout/err StringIO objects"""
291
275
292 def __init__(self, stdout, stderr):
276 def __init__(self, stdout, stderr):
293 self._stdout = stdout
277 self._stdout = stdout
294 self._stderr = stderr
278 self._stderr = stderr
295
279
296 def __str__(self):
280 def __str__(self):
297 return self.stdout
281 return self.stdout
298
282
299 @property
283 @property
300 def stdout(self):
284 def stdout(self):
301 if not self._stdout:
285 if not self._stdout:
302 return ''
286 return ''
303 return self._stdout.getvalue()
287 return self._stdout.getvalue()
304
288
305 @property
289 @property
306 def stderr(self):
290 def stderr(self):
307 if not self._stderr:
291 if not self._stderr:
308 return ''
292 return ''
309 return self._stderr.getvalue()
293 return self._stderr.getvalue()
310
294
311 def show(self):
295 def show(self):
312 """write my output to sys.stdout/err as appropriate"""
296 """write my output to sys.stdout/err as appropriate"""
313 sys.stdout.write(self.stdout)
297 sys.stdout.write(self.stdout)
314 sys.stderr.write(self.stderr)
298 sys.stderr.write(self.stderr)
315 sys.stdout.flush()
299 sys.stdout.flush()
316 sys.stderr.flush()
300 sys.stderr.flush()
317
301
318 __call__ = show
302 __call__ = show
319
303
320
304
321 class capture_output(object):
305 class capture_output(object):
322 """context manager for capturing stdout/err"""
306 """context manager for capturing stdout/err"""
323 stdout = True
307 stdout = True
324 stderr = True
308 stderr = True
325
309
326 def __init__(self, stdout=True, stderr=True):
310 def __init__(self, stdout=True, stderr=True):
327 self.stdout = stdout
311 self.stdout = stdout
328 self.stderr = stderr
312 self.stderr = stderr
329
313
330 def __enter__(self):
314 def __enter__(self):
331 self.sys_stdout = sys.stdout
315 self.sys_stdout = sys.stdout
332 self.sys_stderr = sys.stderr
316 self.sys_stderr = sys.stderr
333
317
334 stdout = stderr = False
318 stdout = stderr = False
335 if self.stdout:
319 if self.stdout:
336 stdout = sys.stdout = StringIO()
320 stdout = sys.stdout = StringIO()
337 if self.stderr:
321 if self.stderr:
338 stderr = sys.stderr = StringIO()
322 stderr = sys.stderr = StringIO()
339
323
340 return CapturedIO(stdout, stderr)
324 return CapturedIO(stdout, stderr)
341
325
342 def __exit__(self, exc_type, exc_value, traceback):
326 def __exit__(self, exc_type, exc_value, traceback):
343 sys.stdout = self.sys_stdout
327 sys.stdout = self.sys_stdout
344 sys.stderr = self.sys_stderr
328 sys.stderr = self.sys_stderr
345
329
346
330
General Comments 0
You need to be logged in to leave comments. Login now