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