##// END OF EJS Templates
Merge pull request #2882 from takluyver/utils-cleanup...
Bussonnier Matthias -
r9486:a3c4e796 merge
parent child Browse files
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,726 +1,726 b''
1 1 """Implementation of magic functions for interaction with the OS.
2 2
3 3 Note: this module is named 'osm' instead of 'os' to avoid a collision with the
4 4 builtin.
5 5 """
6 6 #-----------------------------------------------------------------------------
7 7 # Copyright (c) 2012 The IPython Development Team.
8 8 #
9 9 # Distributed under the terms of the Modified BSD License.
10 10 #
11 11 # The full license is in the file COPYING.txt, distributed with this software.
12 12 #-----------------------------------------------------------------------------
13 13
14 14 #-----------------------------------------------------------------------------
15 15 # Imports
16 16 #-----------------------------------------------------------------------------
17 17
18 18 # Stdlib
19 19 import io
20 20 import os
21 21 import re
22 22 import sys
23 23 from pprint import pformat
24 24
25 25 # Our own packages
26 26 from IPython.core import magic_arguments
27 27 from IPython.core import oinspect
28 28 from IPython.core import page
29 29 from IPython.core.error import UsageError
30 30 from IPython.core.magic import (
31 31 Magics, compress_dhist, magics_class, line_magic, cell_magic, line_cell_magic
32 32 )
33 33 from IPython.testing.skipdoctest import skip_doctest
34 from IPython.utils.io import nlprint
35 34 from IPython.utils.openpy import source_to_unicode
36 35 from IPython.utils.path import unquote_filename
37 36 from IPython.utils.process import abbrev_cwd
38 37 from IPython.utils.terminal import set_term_title
39 38
40 39 #-----------------------------------------------------------------------------
41 40 # Magic implementation classes
42 41 #-----------------------------------------------------------------------------
43 42 @magics_class
44 43 class OSMagics(Magics):
45 44 """Magics to interact with the underlying OS (shell-type functionality).
46 45 """
47 46
48 47 @skip_doctest
49 48 @line_magic
50 49 def alias(self, parameter_s=''):
51 50 """Define an alias for a system command.
52 51
53 52 '%alias alias_name cmd' defines 'alias_name' as an alias for 'cmd'
54 53
55 54 Then, typing 'alias_name params' will execute the system command 'cmd
56 55 params' (from your underlying operating system).
57 56
58 57 Aliases have lower precedence than magic functions and Python normal
59 58 variables, so if 'foo' is both a Python variable and an alias, the
60 59 alias can not be executed until 'del foo' removes the Python variable.
61 60
62 61 You can use the %l specifier in an alias definition to represent the
63 62 whole line when the alias is called. For example::
64 63
65 64 In [2]: alias bracket echo "Input in brackets: <%l>"
66 65 In [3]: bracket hello world
67 66 Input in brackets: <hello world>
68 67
69 68 You can also define aliases with parameters using %s specifiers (one
70 69 per parameter)::
71 70
72 71 In [1]: alias parts echo first %s second %s
73 72 In [2]: %parts A B
74 73 first A second B
75 74 In [3]: %parts A
76 75 Incorrect number of arguments: 2 expected.
77 76 parts is an alias to: 'echo first %s second %s'
78 77
79 78 Note that %l and %s are mutually exclusive. You can only use one or
80 79 the other in your aliases.
81 80
82 81 Aliases expand Python variables just like system calls using ! or !!
83 82 do: all expressions prefixed with '$' get expanded. For details of
84 83 the semantic rules, see PEP-215:
85 84 http://www.python.org/peps/pep-0215.html. This is the library used by
86 85 IPython for variable expansion. If you want to access a true shell
87 86 variable, an extra $ is necessary to prevent its expansion by
88 87 IPython::
89 88
90 89 In [6]: alias show echo
91 90 In [7]: PATH='A Python string'
92 91 In [8]: show $PATH
93 92 A Python string
94 93 In [9]: show $$PATH
95 94 /usr/local/lf9560/bin:/usr/local/intel/compiler70/ia32/bin:...
96 95
97 96 You can use the alias facility to acess all of $PATH. See the %rehash
98 97 and %rehashx functions, which automatically create aliases for the
99 98 contents of your $PATH.
100 99
101 100 If called with no parameters, %alias prints the current alias table."""
102 101
103 102 par = parameter_s.strip()
104 103 if not par:
105 104 aliases = sorted(self.shell.alias_manager.aliases)
106 105 # stored = self.shell.db.get('stored_aliases', {} )
107 106 # for k, v in stored:
108 107 # atab.append(k, v[0])
109 108
110 109 print "Total number of aliases:", len(aliases)
111 110 sys.stdout.flush()
112 111 return aliases
113 112
114 113 # Now try to define a new one
115 114 try:
116 115 alias,cmd = par.split(None, 1)
117 116 except:
118 117 print oinspect.getdoc(self.alias)
119 118 else:
120 119 self.shell.alias_manager.soft_define_alias(alias, cmd)
121 120 # end magic_alias
122 121
123 122 @line_magic
124 123 def unalias(self, parameter_s=''):
125 124 """Remove an alias"""
126 125
127 126 aname = parameter_s.strip()
128 127 self.shell.alias_manager.undefine_alias(aname)
129 128 stored = self.shell.db.get('stored_aliases', {} )
130 129 if aname in stored:
131 130 print "Removing %stored alias",aname
132 131 del stored[aname]
133 132 self.shell.db['stored_aliases'] = stored
134 133
135 134 @line_magic
136 135 def rehashx(self, parameter_s=''):
137 136 """Update the alias table with all executable files in $PATH.
138 137
139 138 This version explicitly checks that every entry in $PATH is a file
140 139 with execute access (os.X_OK), so it is much slower than %rehash.
141 140
142 141 Under Windows, it checks executability as a match against a
143 142 '|'-separated string of extensions, stored in the IPython config
144 143 variable win_exec_ext. This defaults to 'exe|com|bat'.
145 144
146 145 This function also resets the root module cache of module completer,
147 146 used on slow filesystems.
148 147 """
149 148 from IPython.core.alias import InvalidAliasError
150 149
151 150 # for the benefit of module completer in ipy_completers.py
152 151 del self.shell.db['rootmodules']
153 152
154 153 path = [os.path.abspath(os.path.expanduser(p)) for p in
155 154 os.environ.get('PATH','').split(os.pathsep)]
156 155 path = filter(os.path.isdir,path)
157 156
158 157 syscmdlist = []
159 158 # Now define isexec in a cross platform manner.
160 159 if os.name == 'posix':
161 160 isexec = lambda fname:os.path.isfile(fname) and \
162 161 os.access(fname,os.X_OK)
163 162 else:
164 163 try:
165 164 winext = os.environ['pathext'].replace(';','|').replace('.','')
166 165 except KeyError:
167 166 winext = 'exe|com|bat|py'
168 167 if 'py' not in winext:
169 168 winext += '|py'
170 169 execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE)
171 170 isexec = lambda fname:os.path.isfile(fname) and execre.match(fname)
172 171 savedir = os.getcwdu()
173 172
174 173 # Now walk the paths looking for executables to alias.
175 174 try:
176 175 # write the whole loop for posix/Windows so we don't have an if in
177 176 # the innermost part
178 177 if os.name == 'posix':
179 178 for pdir in path:
180 179 os.chdir(pdir)
181 180 for ff in os.listdir(pdir):
182 181 if isexec(ff):
183 182 try:
184 183 # Removes dots from the name since ipython
185 184 # will assume names with dots to be python.
186 185 self.shell.alias_manager.define_alias(
187 186 ff.replace('.',''), ff)
188 187 except InvalidAliasError:
189 188 pass
190 189 else:
191 190 syscmdlist.append(ff)
192 191 else:
193 192 no_alias = self.shell.alias_manager.no_alias
194 193 for pdir in path:
195 194 os.chdir(pdir)
196 195 for ff in os.listdir(pdir):
197 196 base, ext = os.path.splitext(ff)
198 197 if isexec(ff) and base.lower() not in no_alias:
199 198 if ext.lower() == '.exe':
200 199 ff = base
201 200 try:
202 201 # Removes dots from the name since ipython
203 202 # will assume names with dots to be python.
204 203 self.shell.alias_manager.define_alias(
205 204 base.lower().replace('.',''), ff)
206 205 except InvalidAliasError:
207 206 pass
208 207 syscmdlist.append(ff)
209 208 self.shell.db['syscmdlist'] = syscmdlist
210 209 finally:
211 210 os.chdir(savedir)
212 211
213 212 @skip_doctest
214 213 @line_magic
215 214 def pwd(self, parameter_s=''):
216 215 """Return the current working directory path.
217 216
218 217 Examples
219 218 --------
220 219 ::
221 220
222 221 In [9]: pwd
223 222 Out[9]: '/home/tsuser/sprint/ipython'
224 223 """
225 224 return os.getcwdu()
226 225
227 226 @skip_doctest
228 227 @line_magic
229 228 def cd(self, parameter_s=''):
230 229 """Change the current working directory.
231 230
232 231 This command automatically maintains an internal list of directories
233 232 you visit during your IPython session, in the variable _dh. The
234 233 command %dhist shows this history nicely formatted. You can also
235 234 do 'cd -<tab>' to see directory history conveniently.
236 235
237 236 Usage:
238 237
239 238 cd 'dir': changes to directory 'dir'.
240 239
241 240 cd -: changes to the last visited directory.
242 241
243 242 cd -<n>: changes to the n-th directory in the directory history.
244 243
245 244 cd --foo: change to directory that matches 'foo' in history
246 245
247 246 cd -b <bookmark_name>: jump to a bookmark set by %bookmark
248 247 (note: cd <bookmark_name> is enough if there is no
249 248 directory <bookmark_name>, but a bookmark with the name exists.)
250 249 'cd -b <tab>' allows you to tab-complete bookmark names.
251 250
252 251 Options:
253 252
254 253 -q: quiet. Do not print the working directory after the cd command is
255 254 executed. By default IPython's cd command does print this directory,
256 255 since the default prompts do not display path information.
257 256
258 257 Note that !cd doesn't work for this purpose because the shell where
259 258 !command runs is immediately discarded after executing 'command'.
260 259
261 260 Examples
262 261 --------
263 262 ::
264 263
265 264 In [10]: cd parent/child
266 265 /home/tsuser/parent/child
267 266 """
268 267
269 268 oldcwd = os.getcwdu()
270 269 numcd = re.match(r'(-)(\d+)$',parameter_s)
271 270 # jump in directory history by number
272 271 if numcd:
273 272 nn = int(numcd.group(2))
274 273 try:
275 274 ps = self.shell.user_ns['_dh'][nn]
276 275 except IndexError:
277 276 print 'The requested directory does not exist in history.'
278 277 return
279 278 else:
280 279 opts = {}
281 280 elif parameter_s.startswith('--'):
282 281 ps = None
283 282 fallback = None
284 283 pat = parameter_s[2:]
285 284 dh = self.shell.user_ns['_dh']
286 285 # first search only by basename (last component)
287 286 for ent in reversed(dh):
288 287 if pat in os.path.basename(ent) and os.path.isdir(ent):
289 288 ps = ent
290 289 break
291 290
292 291 if fallback is None and pat in ent and os.path.isdir(ent):
293 292 fallback = ent
294 293
295 294 # if we have no last part match, pick the first full path match
296 295 if ps is None:
297 296 ps = fallback
298 297
299 298 if ps is None:
300 299 print "No matching entry in directory history"
301 300 return
302 301 else:
303 302 opts = {}
304 303
305 304
306 305 else:
307 306 #turn all non-space-escaping backslashes to slashes,
308 307 # for c:\windows\directory\names\
309 308 parameter_s = re.sub(r'\\(?! )','/', parameter_s)
310 309 opts,ps = self.parse_options(parameter_s,'qb',mode='string')
311 310 # jump to previous
312 311 if ps == '-':
313 312 try:
314 313 ps = self.shell.user_ns['_dh'][-2]
315 314 except IndexError:
316 315 raise UsageError('%cd -: No previous directory to change to.')
317 316 # jump to bookmark if needed
318 317 else:
319 318 if not os.path.isdir(ps) or 'b' in opts:
320 319 bkms = self.shell.db.get('bookmarks', {})
321 320
322 321 if ps in bkms:
323 322 target = bkms[ps]
324 323 print '(bookmark:%s) -> %s' % (ps, target)
325 324 ps = target
326 325 else:
327 326 if 'b' in opts:
328 327 raise UsageError("Bookmark '%s' not found. "
329 328 "Use '%%bookmark -l' to see your bookmarks." % ps)
330 329
331 330 # strip extra quotes on Windows, because os.chdir doesn't like them
332 331 ps = unquote_filename(ps)
333 332 # at this point ps should point to the target dir
334 333 if ps:
335 334 try:
336 335 os.chdir(os.path.expanduser(ps))
337 336 if hasattr(self.shell, 'term_title') and self.shell.term_title:
338 337 set_term_title('IPython: ' + abbrev_cwd())
339 338 except OSError:
340 339 print sys.exc_info()[1]
341 340 else:
342 341 cwd = os.getcwdu()
343 342 dhist = self.shell.user_ns['_dh']
344 343 if oldcwd != cwd:
345 344 dhist.append(cwd)
346 345 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
347 346
348 347 else:
349 348 os.chdir(self.shell.home_dir)
350 349 if hasattr(self.shell, 'term_title') and self.shell.term_title:
351 350 set_term_title('IPython: ' + '~')
352 351 cwd = os.getcwdu()
353 352 dhist = self.shell.user_ns['_dh']
354 353
355 354 if oldcwd != cwd:
356 355 dhist.append(cwd)
357 356 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
358 357 if not 'q' in opts and self.shell.user_ns['_dh']:
359 358 print self.shell.user_ns['_dh'][-1]
360 359
361 360
362 361 @line_magic
363 362 def env(self, parameter_s=''):
364 363 """List environment variables."""
365 364
366 365 return dict(os.environ)
367 366
368 367 @line_magic
369 368 def pushd(self, parameter_s=''):
370 369 """Place the current dir on stack and change directory.
371 370
372 371 Usage:\\
373 372 %pushd ['dirname']
374 373 """
375 374
376 375 dir_s = self.shell.dir_stack
377 376 tgt = os.path.expanduser(unquote_filename(parameter_s))
378 377 cwd = os.getcwdu().replace(self.shell.home_dir,'~')
379 378 if tgt:
380 379 self.cd(parameter_s)
381 380 dir_s.insert(0,cwd)
382 381 return self.shell.magic('dirs')
383 382
384 383 @line_magic
385 384 def popd(self, parameter_s=''):
386 385 """Change to directory popped off the top of the stack.
387 386 """
388 387 if not self.shell.dir_stack:
389 388 raise UsageError("%popd on empty stack")
390 389 top = self.shell.dir_stack.pop(0)
391 390 self.cd(top)
392 391 print "popd ->",top
393 392
394 393 @line_magic
395 394 def dirs(self, parameter_s=''):
396 395 """Return the current directory stack."""
397 396
398 397 return self.shell.dir_stack
399 398
400 399 @line_magic
401 400 def dhist(self, parameter_s=''):
402 401 """Print your history of visited directories.
403 402
404 403 %dhist -> print full history\\
405 404 %dhist n -> print last n entries only\\
406 %dhist n1 n2 -> print entries between n1 and n2 (n1 not included)\\
405 %dhist n1 n2 -> print entries between n1 and n2 (n2 not included)\\
407 406
408 407 This history is automatically maintained by the %cd command, and
409 408 always available as the global list variable _dh. You can use %cd -<n>
410 409 to go to directory number <n>.
411 410
412 411 Note that most of time, you should view directory history by entering
413 412 cd -<TAB>.
414 413
415 414 """
416 415
417 416 dh = self.shell.user_ns['_dh']
418 417 if parameter_s:
419 418 try:
420 419 args = map(int,parameter_s.split())
421 420 except:
422 421 self.arg_err(self.dhist)
423 422 return
424 423 if len(args) == 1:
425 424 ini,fin = max(len(dh)-(args[0]),0),len(dh)
426 425 elif len(args) == 2:
427 426 ini,fin = args
427 fin = min(fin, len(dh))
428 428 else:
429 429 self.arg_err(self.dhist)
430 430 return
431 431 else:
432 432 ini,fin = 0,len(dh)
433 nlprint(dh,
434 header = 'Directory history (kept in _dh)',
435 start=ini,stop=fin)
433 print 'Directory history (kept in _dh)'
434 for i in range(ini, fin):
435 print "%d: %s" % (i, dh[i])
436 436
437 437 @skip_doctest
438 438 @line_magic
439 439 def sc(self, parameter_s=''):
440 440 """Shell capture - run shell command and capture output (DEPRECATED use !).
441 441
442 442 DEPRECATED. Suboptimal, retained for backwards compatibility.
443 443
444 444 You should use the form 'var = !command' instead. Example:
445 445
446 446 "%sc -l myfiles = ls ~" should now be written as
447 447
448 448 "myfiles = !ls ~"
449 449
450 450 myfiles.s, myfiles.l and myfiles.n still apply as documented
451 451 below.
452 452
453 453 --
454 454 %sc [options] varname=command
455 455
456 456 IPython will run the given command using commands.getoutput(), and
457 457 will then update the user's interactive namespace with a variable
458 458 called varname, containing the value of the call. Your command can
459 459 contain shell wildcards, pipes, etc.
460 460
461 461 The '=' sign in the syntax is mandatory, and the variable name you
462 462 supply must follow Python's standard conventions for valid names.
463 463
464 464 (A special format without variable name exists for internal use)
465 465
466 466 Options:
467 467
468 468 -l: list output. Split the output on newlines into a list before
469 469 assigning it to the given variable. By default the output is stored
470 470 as a single string.
471 471
472 472 -v: verbose. Print the contents of the variable.
473 473
474 474 In most cases you should not need to split as a list, because the
475 475 returned value is a special type of string which can automatically
476 476 provide its contents either as a list (split on newlines) or as a
477 477 space-separated string. These are convenient, respectively, either
478 478 for sequential processing or to be passed to a shell command.
479 479
480 480 For example::
481 481
482 482 # Capture into variable a
483 483 In [1]: sc a=ls *py
484 484
485 485 # a is a string with embedded newlines
486 486 In [2]: a
487 487 Out[2]: 'setup.py\\nwin32_manual_post_install.py'
488 488
489 489 # which can be seen as a list:
490 490 In [3]: a.l
491 491 Out[3]: ['setup.py', 'win32_manual_post_install.py']
492 492
493 493 # or as a whitespace-separated string:
494 494 In [4]: a.s
495 495 Out[4]: 'setup.py win32_manual_post_install.py'
496 496
497 497 # a.s is useful to pass as a single command line:
498 498 In [5]: !wc -l $a.s
499 499 146 setup.py
500 500 130 win32_manual_post_install.py
501 501 276 total
502 502
503 503 # while the list form is useful to loop over:
504 504 In [6]: for f in a.l:
505 505 ...: !wc -l $f
506 506 ...:
507 507 146 setup.py
508 508 130 win32_manual_post_install.py
509 509
510 510 Similarly, the lists returned by the -l option are also special, in
511 511 the sense that you can equally invoke the .s attribute on them to
512 512 automatically get a whitespace-separated string from their contents::
513 513
514 514 In [7]: sc -l b=ls *py
515 515
516 516 In [8]: b
517 517 Out[8]: ['setup.py', 'win32_manual_post_install.py']
518 518
519 519 In [9]: b.s
520 520 Out[9]: 'setup.py win32_manual_post_install.py'
521 521
522 522 In summary, both the lists and strings used for output capture have
523 523 the following special attributes::
524 524
525 525 .l (or .list) : value as list.
526 526 .n (or .nlstr): value as newline-separated string.
527 527 .s (or .spstr): value as space-separated string.
528 528 """
529 529
530 530 opts,args = self.parse_options(parameter_s, 'lv')
531 531 # Try to get a variable name and command to run
532 532 try:
533 533 # the variable name must be obtained from the parse_options
534 534 # output, which uses shlex.split to strip options out.
535 535 var,_ = args.split('=', 1)
536 536 var = var.strip()
537 537 # But the command has to be extracted from the original input
538 538 # parameter_s, not on what parse_options returns, to avoid the
539 539 # quote stripping which shlex.split performs on it.
540 540 _,cmd = parameter_s.split('=', 1)
541 541 except ValueError:
542 542 var,cmd = '',''
543 543 # If all looks ok, proceed
544 544 split = 'l' in opts
545 545 out = self.shell.getoutput(cmd, split=split)
546 546 if 'v' in opts:
547 547 print '%s ==\n%s' % (var, pformat(out))
548 548 if var:
549 549 self.shell.user_ns.update({var:out})
550 550 else:
551 551 return out
552 552
553 553 @line_cell_magic
554 554 def sx(self, line='', cell=None):
555 555 """Shell execute - run shell command and capture output (!! is short-hand).
556 556
557 557 %sx command
558 558
559 559 IPython will run the given command using commands.getoutput(), and
560 560 return the result formatted as a list (split on '\\n'). Since the
561 561 output is _returned_, it will be stored in ipython's regular output
562 562 cache Out[N] and in the '_N' automatic variables.
563 563
564 564 Notes:
565 565
566 566 1) If an input line begins with '!!', then %sx is automatically
567 567 invoked. That is, while::
568 568
569 569 !ls
570 570
571 571 causes ipython to simply issue system('ls'), typing::
572 572
573 573 !!ls
574 574
575 575 is a shorthand equivalent to::
576 576
577 577 %sx ls
578 578
579 579 2) %sx differs from %sc in that %sx automatically splits into a list,
580 580 like '%sc -l'. The reason for this is to make it as easy as possible
581 581 to process line-oriented shell output via further python commands.
582 582 %sc is meant to provide much finer control, but requires more
583 583 typing.
584 584
585 585 3) Just like %sc -l, this is a list with special attributes:
586 586 ::
587 587
588 588 .l (or .list) : value as list.
589 589 .n (or .nlstr): value as newline-separated string.
590 590 .s (or .spstr): value as whitespace-separated string.
591 591
592 592 This is very useful when trying to use such lists as arguments to
593 593 system commands."""
594 594
595 595 if cell is None:
596 596 # line magic
597 597 return self.shell.getoutput(line)
598 598 else:
599 599 opts,args = self.parse_options(line, '', 'out=')
600 600 output = self.shell.getoutput(cell)
601 601 out_name = opts.get('out', opts.get('o'))
602 602 if out_name:
603 603 self.shell.user_ns[out_name] = output
604 604 else:
605 605 return output
606 606
607 607 system = line_cell_magic('system')(sx)
608 608 bang = cell_magic('!')(sx)
609 609
610 610 @line_magic
611 611 def bookmark(self, parameter_s=''):
612 612 """Manage IPython's bookmark system.
613 613
614 614 %bookmark <name> - set bookmark to current dir
615 615 %bookmark <name> <dir> - set bookmark to <dir>
616 616 %bookmark -l - list all bookmarks
617 617 %bookmark -d <name> - remove bookmark
618 618 %bookmark -r - remove all bookmarks
619 619
620 620 You can later on access a bookmarked folder with::
621 621
622 622 %cd -b <name>
623 623
624 624 or simply '%cd <name>' if there is no directory called <name> AND
625 625 there is such a bookmark defined.
626 626
627 627 Your bookmarks persist through IPython sessions, but they are
628 628 associated with each profile."""
629 629
630 630 opts,args = self.parse_options(parameter_s,'drl',mode='list')
631 631 if len(args) > 2:
632 632 raise UsageError("%bookmark: too many arguments")
633 633
634 634 bkms = self.shell.db.get('bookmarks',{})
635 635
636 636 if 'd' in opts:
637 637 try:
638 638 todel = args[0]
639 639 except IndexError:
640 640 raise UsageError(
641 641 "%bookmark -d: must provide a bookmark to delete")
642 642 else:
643 643 try:
644 644 del bkms[todel]
645 645 except KeyError:
646 646 raise UsageError(
647 647 "%%bookmark -d: Can't delete bookmark '%s'" % todel)
648 648
649 649 elif 'r' in opts:
650 650 bkms = {}
651 651 elif 'l' in opts:
652 652 bks = bkms.keys()
653 653 bks.sort()
654 654 if bks:
655 655 size = max(map(len, bks))
656 656 else:
657 657 size = 0
658 658 fmt = '%-'+str(size)+'s -> %s'
659 659 print 'Current bookmarks:'
660 660 for bk in bks:
661 661 print fmt % (bk, bkms[bk])
662 662 else:
663 663 if not args:
664 664 raise UsageError("%bookmark: You must specify the bookmark name")
665 665 elif len(args)==1:
666 666 bkms[args[0]] = os.getcwdu()
667 667 elif len(args)==2:
668 668 bkms[args[0]] = args[1]
669 669 self.shell.db['bookmarks'] = bkms
670 670
671 671 @line_magic
672 672 def pycat(self, parameter_s=''):
673 673 """Show a syntax-highlighted file through a pager.
674 674
675 675 This magic is similar to the cat utility, but it will assume the file
676 676 to be Python source and will show it with syntax highlighting.
677 677
678 678 This magic command can either take a local filename, an url,
679 679 an history range (see %history) or a macro as argument ::
680 680
681 681 %pycat myscript.py
682 682 %pycat 7-27
683 683 %pycat myMacro
684 684 %pycat http://www.example.com/myscript.py
685 685 """
686 686 if not parameter_s:
687 687 raise UsageError('Missing filename, URL, input history range, '
688 688 'or macro.')
689 689
690 690 try :
691 691 cont = self.shell.find_user_code(parameter_s, skip_encoding_cookie=False)
692 692 except (ValueError, IOError):
693 693 print "Error: no such file, variable, URL, history range or macro"
694 694 return
695 695
696 696 page.page(self.shell.pycolorize(source_to_unicode(cont)))
697 697
698 698 @magic_arguments.magic_arguments()
699 699 @magic_arguments.argument(
700 700 '-a', '--amend', action='store_true', default=False,
701 701 help='Open file for amending if it exists'
702 702 )
703 703 @magic_arguments.argument(
704 704 'filename', type=unicode,
705 705 help='file to write'
706 706 )
707 707 @cell_magic
708 708 def file(self, line, cell):
709 709 """Write the contents of the cell to a file.
710 710
711 711 For frontends that do not support stdin (Notebook), -f is implied.
712 712 """
713 713 args = magic_arguments.parse_argstring(self.file, line)
714 714 filename = unquote_filename(args.filename)
715 715
716 716 if os.path.exists(filename):
717 717 if args.amend:
718 718 print "Amending to %s" % filename
719 719 else:
720 720 print "Overwriting %s" % filename
721 721 else:
722 722 print "Writing %s" % filename
723 723
724 724 mode = 'a' if args.amend else 'w'
725 725 with io.open(filename, mode, encoding='utf-8') as f:
726 726 f.write(cell)
@@ -1,1246 +1,1246 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 ultratb.py -- Spice up your tracebacks!
4 4
5 5 * ColorTB
6 6 I've always found it a bit hard to visually parse tracebacks in Python. The
7 7 ColorTB class is a solution to that problem. It colors the different parts of a
8 8 traceback in a manner similar to what you would expect from a syntax-highlighting
9 9 text editor.
10 10
11 11 Installation instructions for ColorTB:
12 12 import sys,ultratb
13 13 sys.excepthook = ultratb.ColorTB()
14 14
15 15 * VerboseTB
16 16 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
17 17 of useful info when a traceback occurs. Ping originally had it spit out HTML
18 18 and intended it for CGI programmers, but why should they have all the fun? I
19 19 altered it to spit out colored text to the terminal. It's a bit overwhelming,
20 20 but kind of neat, and maybe useful for long-running programs that you believe
21 21 are bug-free. If a crash *does* occur in that type of program you want details.
22 22 Give it a shot--you'll love it or you'll hate it.
23 23
24 24 Note:
25 25
26 26 The Verbose mode prints the variables currently visible where the exception
27 27 happened (shortening their strings if too long). This can potentially be
28 28 very slow, if you happen to have a huge data structure whose string
29 29 representation is complex to compute. Your computer may appear to freeze for
30 30 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
31 31 with Ctrl-C (maybe hitting it more than once).
32 32
33 33 If you encounter this kind of situation often, you may want to use the
34 34 Verbose_novars mode instead of the regular Verbose, which avoids formatting
35 35 variables (but otherwise includes the information and context given by
36 36 Verbose).
37 37
38 38
39 39 Installation instructions for ColorTB:
40 40 import sys,ultratb
41 41 sys.excepthook = ultratb.VerboseTB()
42 42
43 43 Note: Much of the code in this module was lifted verbatim from the standard
44 44 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
45 45
46 46 * Color schemes
47 47 The colors are defined in the class TBTools through the use of the
48 48 ColorSchemeTable class. Currently the following exist:
49 49
50 50 - NoColor: allows all of this module to be used in any terminal (the color
51 51 escapes are just dummy blank strings).
52 52
53 53 - Linux: is meant to look good in a terminal like the Linux console (black
54 54 or very dark background).
55 55
56 56 - LightBG: similar to Linux but swaps dark/light colors to be more readable
57 57 in light background terminals.
58 58
59 59 You can implement other color schemes easily, the syntax is fairly
60 60 self-explanatory. Please send back new schemes you develop to the author for
61 61 possible inclusion in future releases.
62 62
63 63 Inheritance diagram:
64 64
65 65 .. inheritance-diagram:: IPython.core.ultratb
66 66 :parts: 3
67 67 """
68 68
69 69 #*****************************************************************************
70 70 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
71 71 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
72 72 #
73 73 # Distributed under the terms of the BSD License. The full license is in
74 74 # the file COPYING, distributed as part of this software.
75 75 #*****************************************************************************
76 76
77 77 from __future__ import unicode_literals
78 78
79 79 import inspect
80 80 import keyword
81 81 import linecache
82 82 import os
83 83 import pydoc
84 84 import re
85 85 import sys
86 86 import time
87 87 import tokenize
88 88 import traceback
89 89 import types
90 90
91 91 try: # Python 2
92 92 generate_tokens = tokenize.generate_tokens
93 93 except AttributeError: # Python 3
94 94 generate_tokens = tokenize.tokenize
95 95
96 96 # For purposes of monkeypatching inspect to fix a bug in it.
97 97 from inspect import getsourcefile, getfile, getmodule,\
98 98 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
99 99
100 100 # IPython's own modules
101 101 # Modified pdb which doesn't damage IPython's readline handling
102 102 from IPython.core import debugger, ipapi
103 103 from IPython.core.display_trap import DisplayTrap
104 104 from IPython.core.excolors import exception_colors
105 105 from IPython.utils import PyColorize
106 106 from IPython.utils import io
107 from IPython.utils import openpy
107 108 from IPython.utils import path as util_path
108 109 from IPython.utils import py3compat
109 from IPython.utils import pyfile
110 110 from IPython.utils import ulinecache
111 111 from IPython.utils.data import uniq_stable
112 112 from IPython.utils.warn import info, error
113 113
114 114 # Globals
115 115 # amount of space to put line numbers before verbose tracebacks
116 116 INDENT_SIZE = 8
117 117
118 118 # Default color scheme. This is used, for example, by the traceback
119 119 # formatter. When running in an actual IPython instance, the user's rc.colors
120 120 # value is used, but havinga module global makes this functionality available
121 121 # to users of ultratb who are NOT running inside ipython.
122 122 DEFAULT_SCHEME = 'NoColor'
123 123
124 124 #---------------------------------------------------------------------------
125 125 # Code begins
126 126
127 127 # Utility functions
128 128 def inspect_error():
129 129 """Print a message about internal inspect errors.
130 130
131 131 These are unfortunately quite common."""
132 132
133 133 error('Internal Python error in the inspect module.\n'
134 134 'Below is the traceback from this internal error.\n')
135 135
136 136 # This function is a monkeypatch we apply to the Python inspect module. We have
137 137 # now found when it's needed (see discussion on issue gh-1456), and we have a
138 138 # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if
139 139 # the monkeypatch is not applied. TK, Aug 2012.
140 140 def findsource(object):
141 141 """Return the entire source file and starting line number for an object.
142 142
143 143 The argument may be a module, class, method, function, traceback, frame,
144 144 or code object. The source code is returned as a list of all the lines
145 145 in the file and the line number indexes a line in that list. An IOError
146 146 is raised if the source code cannot be retrieved.
147 147
148 148 FIXED version with which we monkeypatch the stdlib to work around a bug."""
149 149
150 150 file = getsourcefile(object) or getfile(object)
151 151 # If the object is a frame, then trying to get the globals dict from its
152 152 # module won't work. Instead, the frame object itself has the globals
153 153 # dictionary.
154 154 globals_dict = None
155 155 if inspect.isframe(object):
156 156 # XXX: can this ever be false?
157 157 globals_dict = object.f_globals
158 158 else:
159 159 module = getmodule(object, file)
160 160 if module:
161 161 globals_dict = module.__dict__
162 162 lines = linecache.getlines(file, globals_dict)
163 163 if not lines:
164 164 raise IOError('could not get source code')
165 165
166 166 if ismodule(object):
167 167 return lines, 0
168 168
169 169 if isclass(object):
170 170 name = object.__name__
171 171 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
172 172 # make some effort to find the best matching class definition:
173 173 # use the one with the least indentation, which is the one
174 174 # that's most probably not inside a function definition.
175 175 candidates = []
176 176 for i in range(len(lines)):
177 177 match = pat.match(lines[i])
178 178 if match:
179 179 # if it's at toplevel, it's already the best one
180 180 if lines[i][0] == 'c':
181 181 return lines, i
182 182 # else add whitespace to candidate list
183 183 candidates.append((match.group(1), i))
184 184 if candidates:
185 185 # this will sort by whitespace, and by line number,
186 186 # less whitespace first
187 187 candidates.sort()
188 188 return lines, candidates[0][1]
189 189 else:
190 190 raise IOError('could not find class definition')
191 191
192 192 if ismethod(object):
193 193 object = object.im_func
194 194 if isfunction(object):
195 195 object = object.func_code
196 196 if istraceback(object):
197 197 object = object.tb_frame
198 198 if isframe(object):
199 199 object = object.f_code
200 200 if iscode(object):
201 201 if not hasattr(object, 'co_firstlineno'):
202 202 raise IOError('could not find function definition')
203 203 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
204 204 pmatch = pat.match
205 205 # fperez - fix: sometimes, co_firstlineno can give a number larger than
206 206 # the length of lines, which causes an error. Safeguard against that.
207 207 lnum = min(object.co_firstlineno,len(lines))-1
208 208 while lnum > 0:
209 209 if pmatch(lines[lnum]): break
210 210 lnum -= 1
211 211
212 212 return lines, lnum
213 213 raise IOError('could not find code object')
214 214
215 215 # Monkeypatch inspect to apply our bugfix. This code only works with Python >= 2.5
216 216 inspect.findsource = findsource
217 217
218 218 def fix_frame_records_filenames(records):
219 219 """Try to fix the filenames in each record from inspect.getinnerframes().
220 220
221 221 Particularly, modules loaded from within zip files have useless filenames
222 222 attached to their code object, and inspect.getinnerframes() just uses it.
223 223 """
224 224 fixed_records = []
225 225 for frame, filename, line_no, func_name, lines, index in records:
226 226 # Look inside the frame's globals dictionary for __file__, which should
227 227 # be better.
228 228 better_fn = frame.f_globals.get('__file__', None)
229 229 if isinstance(better_fn, str):
230 230 # Check the type just in case someone did something weird with
231 231 # __file__. It might also be None if the error occurred during
232 232 # import.
233 233 filename = better_fn
234 234 fixed_records.append((frame, filename, line_no, func_name, lines, index))
235 235 return fixed_records
236 236
237 237
238 238 def _fixed_getinnerframes(etb, context=1,tb_offset=0):
239 239 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
240 240
241 241 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
242 242
243 243 # If the error is at the console, don't build any context, since it would
244 244 # otherwise produce 5 blank lines printed out (there is no file at the
245 245 # console)
246 246 rec_check = records[tb_offset:]
247 247 try:
248 248 rname = rec_check[0][1]
249 249 if rname == '<ipython console>' or rname.endswith('<string>'):
250 250 return rec_check
251 251 except IndexError:
252 252 pass
253 253
254 254 aux = traceback.extract_tb(etb)
255 255 assert len(records) == len(aux)
256 256 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
257 257 maybeStart = lnum-1 - context//2
258 258 start = max(maybeStart, 0)
259 259 end = start + context
260 260 lines = ulinecache.getlines(file)[start:end]
261 261 buf = list(records[i])
262 262 buf[LNUM_POS] = lnum
263 263 buf[INDEX_POS] = lnum - 1 - start
264 264 buf[LINES_POS] = lines
265 265 records[i] = tuple(buf)
266 266 return records[tb_offset:]
267 267
268 268 # Helper function -- largely belongs to VerboseTB, but we need the same
269 269 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
270 270 # can be recognized properly by ipython.el's py-traceback-line-re
271 271 # (SyntaxErrors have to be treated specially because they have no traceback)
272 272
273 273 _parser = PyColorize.Parser()
274 274
275 275 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None,scheme=None):
276 276 numbers_width = INDENT_SIZE - 1
277 277 res = []
278 278 i = lnum - index
279 279
280 280 # This lets us get fully syntax-highlighted tracebacks.
281 281 if scheme is None:
282 282 ipinst = ipapi.get()
283 283 if ipinst is not None:
284 284 scheme = ipinst.colors
285 285 else:
286 286 scheme = DEFAULT_SCHEME
287 287
288 288 _line_format = _parser.format2
289 289
290 290 for line in lines:
291 291 line = py3compat.cast_unicode(line)
292 292
293 293 new_line, err = _line_format(line, 'str', scheme)
294 294 if not err: line = new_line
295 295
296 296 if i == lnum:
297 297 # This is the line with the error
298 298 pad = numbers_width - len(str(i))
299 299 if pad >= 3:
300 300 marker = '-'*(pad-3) + '-> '
301 301 elif pad == 2:
302 302 marker = '> '
303 303 elif pad == 1:
304 304 marker = '>'
305 305 else:
306 306 marker = ''
307 307 num = marker + str(i)
308 308 line = '%s%s%s %s%s' %(Colors.linenoEm, num,
309 309 Colors.line, line, Colors.Normal)
310 310 else:
311 311 num = '%*s' % (numbers_width,i)
312 312 line = '%s%s%s %s' %(Colors.lineno, num,
313 313 Colors.Normal, line)
314 314
315 315 res.append(line)
316 316 if lvals and i == lnum:
317 317 res.append(lvals + '\n')
318 318 i = i + 1
319 319 return res
320 320
321 321
322 322 #---------------------------------------------------------------------------
323 323 # Module classes
324 324 class TBTools(object):
325 325 """Basic tools used by all traceback printer classes."""
326 326
327 327 # Number of frames to skip when reporting tracebacks
328 328 tb_offset = 0
329 329
330 330 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None):
331 331 # Whether to call the interactive pdb debugger after printing
332 332 # tracebacks or not
333 333 self.call_pdb = call_pdb
334 334
335 335 # Output stream to write to. Note that we store the original value in
336 336 # a private attribute and then make the public ostream a property, so
337 337 # that we can delay accessing io.stdout until runtime. The way
338 338 # things are written now, the io.stdout object is dynamically managed
339 339 # so a reference to it should NEVER be stored statically. This
340 340 # property approach confines this detail to a single location, and all
341 341 # subclasses can simply access self.ostream for writing.
342 342 self._ostream = ostream
343 343
344 344 # Create color table
345 345 self.color_scheme_table = exception_colors()
346 346
347 347 self.set_colors(color_scheme)
348 348 self.old_scheme = color_scheme # save initial value for toggles
349 349
350 350 if call_pdb:
351 351 self.pdb = debugger.Pdb(self.color_scheme_table.active_scheme_name)
352 352 else:
353 353 self.pdb = None
354 354
355 355 def _get_ostream(self):
356 356 """Output stream that exceptions are written to.
357 357
358 358 Valid values are:
359 359
360 360 - None: the default, which means that IPython will dynamically resolve
361 361 to io.stdout. This ensures compatibility with most tools, including
362 362 Windows (where plain stdout doesn't recognize ANSI escapes).
363 363
364 364 - Any object with 'write' and 'flush' attributes.
365 365 """
366 366 return io.stdout if self._ostream is None else self._ostream
367 367
368 368 def _set_ostream(self, val):
369 369 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
370 370 self._ostream = val
371 371
372 372 ostream = property(_get_ostream, _set_ostream)
373 373
374 374 def set_colors(self,*args,**kw):
375 375 """Shorthand access to the color table scheme selector method."""
376 376
377 377 # Set own color table
378 378 self.color_scheme_table.set_active_scheme(*args,**kw)
379 379 # for convenience, set Colors to the active scheme
380 380 self.Colors = self.color_scheme_table.active_colors
381 381 # Also set colors of debugger
382 382 if hasattr(self,'pdb') and self.pdb is not None:
383 383 self.pdb.set_colors(*args,**kw)
384 384
385 385 def color_toggle(self):
386 386 """Toggle between the currently active color scheme and NoColor."""
387 387
388 388 if self.color_scheme_table.active_scheme_name == 'NoColor':
389 389 self.color_scheme_table.set_active_scheme(self.old_scheme)
390 390 self.Colors = self.color_scheme_table.active_colors
391 391 else:
392 392 self.old_scheme = self.color_scheme_table.active_scheme_name
393 393 self.color_scheme_table.set_active_scheme('NoColor')
394 394 self.Colors = self.color_scheme_table.active_colors
395 395
396 396 def stb2text(self, stb):
397 397 """Convert a structured traceback (a list) to a string."""
398 398 return '\n'.join(stb)
399 399
400 400 def text(self, etype, value, tb, tb_offset=None, context=5):
401 401 """Return formatted traceback.
402 402
403 403 Subclasses may override this if they add extra arguments.
404 404 """
405 405 tb_list = self.structured_traceback(etype, value, tb,
406 406 tb_offset, context)
407 407 return self.stb2text(tb_list)
408 408
409 409 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
410 410 context=5, mode=None):
411 411 """Return a list of traceback frames.
412 412
413 413 Must be implemented by each class.
414 414 """
415 415 raise NotImplementedError()
416 416
417 417
418 418 #---------------------------------------------------------------------------
419 419 class ListTB(TBTools):
420 420 """Print traceback information from a traceback list, with optional color.
421 421
422 422 Calling requires 3 arguments: (etype, evalue, elist)
423 423 as would be obtained by::
424 424
425 425 etype, evalue, tb = sys.exc_info()
426 426 if tb:
427 427 elist = traceback.extract_tb(tb)
428 428 else:
429 429 elist = None
430 430
431 431 It can thus be used by programs which need to process the traceback before
432 432 printing (such as console replacements based on the code module from the
433 433 standard library).
434 434
435 435 Because they are meant to be called without a full traceback (only a
436 436 list), instances of this class can't call the interactive pdb debugger."""
437 437
438 438 def __init__(self,color_scheme = 'NoColor', call_pdb=False, ostream=None):
439 439 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
440 440 ostream=ostream)
441 441
442 442 def __call__(self, etype, value, elist):
443 443 self.ostream.flush()
444 444 self.ostream.write(self.text(etype, value, elist))
445 445 self.ostream.write('\n')
446 446
447 447 def structured_traceback(self, etype, value, elist, tb_offset=None,
448 448 context=5):
449 449 """Return a color formatted string with the traceback info.
450 450
451 451 Parameters
452 452 ----------
453 453 etype : exception type
454 454 Type of the exception raised.
455 455
456 456 value : object
457 457 Data stored in the exception
458 458
459 459 elist : list
460 460 List of frames, see class docstring for details.
461 461
462 462 tb_offset : int, optional
463 463 Number of frames in the traceback to skip. If not given, the
464 464 instance value is used (set in constructor).
465 465
466 466 context : int, optional
467 467 Number of lines of context information to print.
468 468
469 469 Returns
470 470 -------
471 471 String with formatted exception.
472 472 """
473 473 tb_offset = self.tb_offset if tb_offset is None else tb_offset
474 474 Colors = self.Colors
475 475 out_list = []
476 476 if elist:
477 477
478 478 if tb_offset and len(elist) > tb_offset:
479 479 elist = elist[tb_offset:]
480 480
481 481 out_list.append('Traceback %s(most recent call last)%s:' %
482 482 (Colors.normalEm, Colors.Normal) + '\n')
483 483 out_list.extend(self._format_list(elist))
484 484 # The exception info should be a single entry in the list.
485 485 lines = ''.join(self._format_exception_only(etype, value))
486 486 out_list.append(lines)
487 487
488 488 # Note: this code originally read:
489 489
490 490 ## for line in lines[:-1]:
491 491 ## out_list.append(" "+line)
492 492 ## out_list.append(lines[-1])
493 493
494 494 # This means it was indenting everything but the last line by a little
495 495 # bit. I've disabled this for now, but if we see ugliness somewhre we
496 496 # can restore it.
497 497
498 498 return out_list
499 499
500 500 def _format_list(self, extracted_list):
501 501 """Format a list of traceback entry tuples for printing.
502 502
503 503 Given a list of tuples as returned by extract_tb() or
504 504 extract_stack(), return a list of strings ready for printing.
505 505 Each string in the resulting list corresponds to the item with the
506 506 same index in the argument list. Each string ends in a newline;
507 507 the strings may contain internal newlines as well, for those items
508 508 whose source text line is not None.
509 509
510 510 Lifted almost verbatim from traceback.py
511 511 """
512 512
513 513 Colors = self.Colors
514 514 list = []
515 515 for filename, lineno, name, line in extracted_list[:-1]:
516 516 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
517 517 (Colors.filename, filename, Colors.Normal,
518 518 Colors.lineno, lineno, Colors.Normal,
519 519 Colors.name, name, Colors.Normal)
520 520 if line:
521 521 item += ' %s\n' % line.strip()
522 522 list.append(item)
523 523 # Emphasize the last entry
524 524 filename, lineno, name, line = extracted_list[-1]
525 525 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
526 526 (Colors.normalEm,
527 527 Colors.filenameEm, filename, Colors.normalEm,
528 528 Colors.linenoEm, lineno, Colors.normalEm,
529 529 Colors.nameEm, name, Colors.normalEm,
530 530 Colors.Normal)
531 531 if line:
532 532 item += '%s %s%s\n' % (Colors.line, line.strip(),
533 533 Colors.Normal)
534 534 list.append(item)
535 535 #from pprint import pformat; print 'LISTTB', pformat(list) # dbg
536 536 return list
537 537
538 538 def _format_exception_only(self, etype, value):
539 539 """Format the exception part of a traceback.
540 540
541 541 The arguments are the exception type and value such as given by
542 542 sys.exc_info()[:2]. The return value is a list of strings, each ending
543 543 in a newline. Normally, the list contains a single string; however,
544 544 for SyntaxError exceptions, it contains several lines that (when
545 545 printed) display detailed information about where the syntax error
546 546 occurred. The message indicating which exception occurred is the
547 547 always last string in the list.
548 548
549 549 Also lifted nearly verbatim from traceback.py
550 550 """
551 551 have_filedata = False
552 552 Colors = self.Colors
553 553 list = []
554 554 stype = Colors.excName + etype.__name__ + Colors.Normal
555 555 if value is None:
556 556 # Not sure if this can still happen in Python 2.6 and above
557 557 list.append( py3compat.cast_unicode(stype) + '\n')
558 558 else:
559 559 if issubclass(etype, SyntaxError):
560 560 have_filedata = True
561 561 #print 'filename is',filename # dbg
562 562 if not value.filename: value.filename = "<string>"
563 563 if value.lineno:
564 564 lineno = value.lineno
565 565 textline = ulinecache.getline(value.filename, value.lineno)
566 566 else:
567 567 lineno = 'unknown'
568 568 textline = ''
569 569 list.append('%s File %s"%s"%s, line %s%s%s\n' % \
570 570 (Colors.normalEm,
571 571 Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm,
572 572 Colors.linenoEm, lineno, Colors.Normal ))
573 573 if textline == '':
574 574 textline = py3compat.cast_unicode(value.text, "utf-8")
575 575
576 576 if textline is not None:
577 577 i = 0
578 578 while i < len(textline) and textline[i].isspace():
579 579 i += 1
580 580 list.append('%s %s%s\n' % (Colors.line,
581 581 textline.strip(),
582 582 Colors.Normal))
583 583 if value.offset is not None:
584 584 s = ' '
585 585 for c in textline[i:value.offset-1]:
586 586 if c.isspace():
587 587 s += c
588 588 else:
589 589 s += ' '
590 590 list.append('%s%s^%s\n' % (Colors.caret, s,
591 591 Colors.Normal) )
592 592
593 593 try:
594 594 s = value.msg
595 595 except Exception:
596 596 s = self._some_str(value)
597 597 if s:
598 598 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
599 599 Colors.Normal, s))
600 600 else:
601 601 list.append('%s\n' % str(stype))
602 602
603 603 # sync with user hooks
604 604 if have_filedata:
605 605 ipinst = ipapi.get()
606 606 if ipinst is not None:
607 607 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
608 608
609 609 return list
610 610
611 611 def get_exception_only(self, etype, value):
612 612 """Only print the exception type and message, without a traceback.
613 613
614 614 Parameters
615 615 ----------
616 616 etype : exception type
617 617 value : exception value
618 618 """
619 619 return ListTB.structured_traceback(self, etype, value, [])
620 620
621 621
622 622 def show_exception_only(self, etype, evalue):
623 623 """Only print the exception type and message, without a traceback.
624 624
625 625 Parameters
626 626 ----------
627 627 etype : exception type
628 628 value : exception value
629 629 """
630 630 # This method needs to use __call__ from *this* class, not the one from
631 631 # a subclass whose signature or behavior may be different
632 632 ostream = self.ostream
633 633 ostream.flush()
634 634 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
635 635 ostream.flush()
636 636
637 637 def _some_str(self, value):
638 638 # Lifted from traceback.py
639 639 try:
640 640 return str(value)
641 641 except:
642 642 return '<unprintable %s object>' % type(value).__name__
643 643
644 644 #----------------------------------------------------------------------------
645 645 class VerboseTB(TBTools):
646 646 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
647 647 of HTML. Requires inspect and pydoc. Crazy, man.
648 648
649 649 Modified version which optionally strips the topmost entries from the
650 650 traceback, to be used with alternate interpreters (because their own code
651 651 would appear in the traceback)."""
652 652
653 653 def __init__(self,color_scheme = 'Linux', call_pdb=False, ostream=None,
654 654 tb_offset=0, long_header=False, include_vars=True,
655 655 check_cache=None):
656 656 """Specify traceback offset, headers and color scheme.
657 657
658 658 Define how many frames to drop from the tracebacks. Calling it with
659 659 tb_offset=1 allows use of this handler in interpreters which will have
660 660 their own code at the top of the traceback (VerboseTB will first
661 661 remove that frame before printing the traceback info)."""
662 662 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
663 663 ostream=ostream)
664 664 self.tb_offset = tb_offset
665 665 self.long_header = long_header
666 666 self.include_vars = include_vars
667 667 # By default we use linecache.checkcache, but the user can provide a
668 668 # different check_cache implementation. This is used by the IPython
669 669 # kernel to provide tracebacks for interactive code that is cached,
670 670 # by a compiler instance that flushes the linecache but preserves its
671 671 # own code cache.
672 672 if check_cache is None:
673 673 check_cache = linecache.checkcache
674 674 self.check_cache = check_cache
675 675
676 676 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
677 677 context=5):
678 678 """Return a nice text document describing the traceback."""
679 679
680 680 tb_offset = self.tb_offset if tb_offset is None else tb_offset
681 681
682 682 # some locals
683 683 try:
684 684 etype = etype.__name__
685 685 except AttributeError:
686 686 pass
687 687 Colors = self.Colors # just a shorthand + quicker name lookup
688 688 ColorsNormal = Colors.Normal # used a lot
689 689 col_scheme = self.color_scheme_table.active_scheme_name
690 690 indent = ' '*INDENT_SIZE
691 691 em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal)
692 692 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
693 693 exc = '%s%s%s' % (Colors.excName,etype,ColorsNormal)
694 694
695 695 # some internal-use functions
696 696 def text_repr(value):
697 697 """Hopefully pretty robust repr equivalent."""
698 698 # this is pretty horrible but should always return *something*
699 699 try:
700 700 return pydoc.text.repr(value)
701 701 except KeyboardInterrupt:
702 702 raise
703 703 except:
704 704 try:
705 705 return repr(value)
706 706 except KeyboardInterrupt:
707 707 raise
708 708 except:
709 709 try:
710 710 # all still in an except block so we catch
711 711 # getattr raising
712 712 name = getattr(value, '__name__', None)
713 713 if name:
714 714 # ick, recursion
715 715 return text_repr(name)
716 716 klass = getattr(value, '__class__', None)
717 717 if klass:
718 718 return '%s instance' % text_repr(klass)
719 719 except KeyboardInterrupt:
720 720 raise
721 721 except:
722 722 return 'UNRECOVERABLE REPR FAILURE'
723 723 def eqrepr(value, repr=text_repr): return '=%s' % repr(value)
724 724 def nullrepr(value, repr=text_repr): return ''
725 725
726 726 # meat of the code begins
727 727 try:
728 728 etype = etype.__name__
729 729 except AttributeError:
730 730 pass
731 731
732 732 if self.long_header:
733 733 # Header with the exception type, python version, and date
734 734 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
735 735 date = time.ctime(time.time())
736 736
737 737 head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal,
738 738 exc, ' '*(75-len(str(etype))-len(pyver)),
739 739 pyver, date.rjust(75) )
740 740 head += "\nA problem occured executing Python code. Here is the sequence of function"\
741 741 "\ncalls leading up to the error, with the most recent (innermost) call last."
742 742 else:
743 743 # Simplified header
744 744 head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc,
745 745 'Traceback (most recent call last)'.\
746 746 rjust(75 - len(str(etype)) ) )
747 747 frames = []
748 748 # Flush cache before calling inspect. This helps alleviate some of the
749 749 # problems with python 2.3's inspect.py.
750 750 ##self.check_cache()
751 751 # Drop topmost frames if requested
752 752 try:
753 753 # Try the default getinnerframes and Alex's: Alex's fixes some
754 754 # problems, but it generates empty tracebacks for console errors
755 755 # (5 blanks lines) where none should be returned.
756 756 #records = inspect.getinnerframes(etb, context)[tb_offset:]
757 757 #print 'python records:', records # dbg
758 758 records = _fixed_getinnerframes(etb, context, tb_offset)
759 759 #print 'alex records:', records # dbg
760 760 except:
761 761
762 762 # FIXME: I've been getting many crash reports from python 2.3
763 763 # users, traceable to inspect.py. If I can find a small test-case
764 764 # to reproduce this, I should either write a better workaround or
765 765 # file a bug report against inspect (if that's the real problem).
766 766 # So far, I haven't been able to find an isolated example to
767 767 # reproduce the problem.
768 768 inspect_error()
769 769 traceback.print_exc(file=self.ostream)
770 770 info('\nUnfortunately, your original traceback can not be constructed.\n')
771 771 return ''
772 772
773 773 # build some color string templates outside these nested loops
774 774 tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal)
775 775 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
776 776 ColorsNormal)
777 777 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
778 778 (Colors.vName, Colors.valEm, ColorsNormal)
779 779 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
780 780 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
781 781 Colors.vName, ColorsNormal)
782 782 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
783 783 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
784 784 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line,
785 785 ColorsNormal)
786 786
787 787 # now, loop over all records printing context and info
788 788 abspath = os.path.abspath
789 789 for frame, file, lnum, func, lines, index in records:
790 790 #print '*** record:',file,lnum,func,lines,index # dbg
791 791 if not file:
792 792 file = '?'
793 793 elif not(file.startswith(str("<")) and file.endswith(str(">"))):
794 794 # Guess that filenames like <string> aren't real filenames, so
795 795 # don't call abspath on them.
796 796 try:
797 797 file = abspath(file)
798 798 except OSError:
799 799 # Not sure if this can still happen: abspath now works with
800 800 # file names like <string>
801 801 pass
802 802 file = py3compat.cast_unicode(file, util_path.fs_encoding)
803 803 link = tpl_link % file
804 804 args, varargs, varkw, locals = inspect.getargvalues(frame)
805 805
806 806 if func == '?':
807 807 call = ''
808 808 else:
809 809 # Decide whether to include variable details or not
810 810 var_repr = self.include_vars and eqrepr or nullrepr
811 811 try:
812 812 call = tpl_call % (func,inspect.formatargvalues(args,
813 813 varargs, varkw,
814 814 locals,formatvalue=var_repr))
815 815 except KeyError:
816 816 # This happens in situations like errors inside generator
817 817 # expressions, where local variables are listed in the
818 818 # line, but can't be extracted from the frame. I'm not
819 819 # 100% sure this isn't actually a bug in inspect itself,
820 820 # but since there's no info for us to compute with, the
821 821 # best we can do is report the failure and move on. Here
822 822 # we must *not* call any traceback construction again,
823 823 # because that would mess up use of %debug later on. So we
824 824 # simply report the failure and move on. The only
825 825 # limitation will be that this frame won't have locals
826 826 # listed in the call signature. Quite subtle problem...
827 827 # I can't think of a good way to validate this in a unit
828 828 # test, but running a script consisting of:
829 829 # dict( (k,v.strip()) for (k,v) in range(10) )
830 830 # will illustrate the error, if this exception catch is
831 831 # disabled.
832 832 call = tpl_call_fail % func
833 833
834 834 # Don't attempt to tokenize binary files.
835 835 if file.endswith(('.so', '.pyd', '.dll')):
836 836 frames.append('%s %s\n' % (link,call))
837 837 continue
838 838 elif file.endswith(('.pyc','.pyo')):
839 839 # Look up the corresponding source file.
840 file = pyfile.source_from_cache(file)
840 file = openpy.source_from_cache(file)
841 841
842 842 def linereader(file=file, lnum=[lnum], getline=ulinecache.getline):
843 843 line = getline(file, lnum[0])
844 844 lnum[0] += 1
845 845 return line
846 846
847 847 # Build the list of names on this line of code where the exception
848 848 # occurred.
849 849 try:
850 850 names = []
851 851 name_cont = False
852 852
853 853 for token_type, token, start, end, line in generate_tokens(linereader):
854 854 # build composite names
855 855 if token_type == tokenize.NAME and token not in keyword.kwlist:
856 856 if name_cont:
857 857 # Continuation of a dotted name
858 858 try:
859 859 names[-1].append(token)
860 860 except IndexError:
861 861 names.append([token])
862 862 name_cont = False
863 863 else:
864 864 # Regular new names. We append everything, the caller
865 865 # will be responsible for pruning the list later. It's
866 866 # very tricky to try to prune as we go, b/c composite
867 867 # names can fool us. The pruning at the end is easy
868 868 # to do (or the caller can print a list with repeated
869 869 # names if so desired.
870 870 names.append([token])
871 871 elif token == '.':
872 872 name_cont = True
873 873 elif token_type == tokenize.NEWLINE:
874 874 break
875 875
876 876 except (IndexError, UnicodeDecodeError):
877 877 # signals exit of tokenizer
878 878 pass
879 879 except tokenize.TokenError as msg:
880 880 _m = ("An unexpected error occurred while tokenizing input\n"
881 881 "The following traceback may be corrupted or invalid\n"
882 882 "The error message is: %s\n" % msg)
883 883 error(_m)
884 884
885 885 # Join composite names (e.g. "dict.fromkeys")
886 886 names = ['.'.join(n) for n in names]
887 887 # prune names list of duplicates, but keep the right order
888 888 unique_names = uniq_stable(names)
889 889
890 890 # Start loop over vars
891 891 lvals = []
892 892 if self.include_vars:
893 893 for name_full in unique_names:
894 894 name_base = name_full.split('.',1)[0]
895 895 if name_base in frame.f_code.co_varnames:
896 896 if name_base in locals:
897 897 try:
898 898 value = repr(eval(name_full,locals))
899 899 except:
900 900 value = undefined
901 901 else:
902 902 value = undefined
903 903 name = tpl_local_var % name_full
904 904 else:
905 905 if name_base in frame.f_globals:
906 906 try:
907 907 value = repr(eval(name_full,frame.f_globals))
908 908 except:
909 909 value = undefined
910 910 else:
911 911 value = undefined
912 912 name = tpl_global_var % name_full
913 913 lvals.append(tpl_name_val % (name,value))
914 914 if lvals:
915 915 lvals = '%s%s' % (indent,em_normal.join(lvals))
916 916 else:
917 917 lvals = ''
918 918
919 919 level = '%s %s\n' % (link,call)
920 920
921 921 if index is None:
922 922 frames.append(level)
923 923 else:
924 924 frames.append('%s%s' % (level,''.join(
925 925 _format_traceback_lines(lnum,index,lines,Colors,lvals,
926 926 col_scheme))))
927 927
928 928 # Get (safely) a string form of the exception info
929 929 try:
930 930 etype_str,evalue_str = map(str,(etype,evalue))
931 931 except:
932 932 # User exception is improperly defined.
933 933 etype,evalue = str,sys.exc_info()[:2]
934 934 etype_str,evalue_str = map(str,(etype,evalue))
935 935 # ... and format it
936 936 exception = ['%s%s%s: %s' % (Colors.excName, etype_str,
937 937 ColorsNormal, py3compat.cast_unicode(evalue_str))]
938 938 if (not py3compat.PY3) and type(evalue) is types.InstanceType:
939 939 try:
940 940 names = [w for w in dir(evalue) if isinstance(w, basestring)]
941 941 except:
942 942 # Every now and then, an object with funny inernals blows up
943 943 # when dir() is called on it. We do the best we can to report
944 944 # the problem and continue
945 945 _m = '%sException reporting error (object with broken dir())%s:'
946 946 exception.append(_m % (Colors.excName,ColorsNormal))
947 947 etype_str,evalue_str = map(str,sys.exc_info()[:2])
948 948 exception.append('%s%s%s: %s' % (Colors.excName,etype_str,
949 949 ColorsNormal, py3compat.cast_unicode(evalue_str)))
950 950 names = []
951 951 for name in names:
952 952 value = text_repr(getattr(evalue, name))
953 953 exception.append('\n%s%s = %s' % (indent, name, value))
954 954
955 955 # vds: >>
956 956 if records:
957 957 filepath, lnum = records[-1][1:3]
958 958 #print "file:", str(file), "linenb", str(lnum) # dbg
959 959 filepath = os.path.abspath(filepath)
960 960 ipinst = ipapi.get()
961 961 if ipinst is not None:
962 962 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
963 963 # vds: <<
964 964
965 965 # return all our info assembled as a single string
966 966 # return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
967 967 return [head] + frames + [''.join(exception[0])]
968 968
969 969 def debugger(self,force=False):
970 970 """Call up the pdb debugger if desired, always clean up the tb
971 971 reference.
972 972
973 973 Keywords:
974 974
975 975 - force(False): by default, this routine checks the instance call_pdb
976 976 flag and does not actually invoke the debugger if the flag is false.
977 977 The 'force' option forces the debugger to activate even if the flag
978 978 is false.
979 979
980 980 If the call_pdb flag is set, the pdb interactive debugger is
981 981 invoked. In all cases, the self.tb reference to the current traceback
982 982 is deleted to prevent lingering references which hamper memory
983 983 management.
984 984
985 985 Note that each call to pdb() does an 'import readline', so if your app
986 986 requires a special setup for the readline completers, you'll have to
987 987 fix that by hand after invoking the exception handler."""
988 988
989 989 if force or self.call_pdb:
990 990 if self.pdb is None:
991 991 self.pdb = debugger.Pdb(
992 992 self.color_scheme_table.active_scheme_name)
993 993 # the system displayhook may have changed, restore the original
994 994 # for pdb
995 995 display_trap = DisplayTrap(hook=sys.__displayhook__)
996 996 with display_trap:
997 997 self.pdb.reset()
998 998 # Find the right frame so we don't pop up inside ipython itself
999 999 if hasattr(self,'tb') and self.tb is not None:
1000 1000 etb = self.tb
1001 1001 else:
1002 1002 etb = self.tb = sys.last_traceback
1003 1003 while self.tb is not None and self.tb.tb_next is not None:
1004 1004 self.tb = self.tb.tb_next
1005 1005 if etb and etb.tb_next:
1006 1006 etb = etb.tb_next
1007 1007 self.pdb.botframe = etb.tb_frame
1008 1008 self.pdb.interaction(self.tb.tb_frame, self.tb)
1009 1009
1010 1010 if hasattr(self,'tb'):
1011 1011 del self.tb
1012 1012
1013 1013 def handler(self, info=None):
1014 1014 (etype, evalue, etb) = info or sys.exc_info()
1015 1015 self.tb = etb
1016 1016 ostream = self.ostream
1017 1017 ostream.flush()
1018 1018 ostream.write(self.text(etype, evalue, etb))
1019 1019 ostream.write('\n')
1020 1020 ostream.flush()
1021 1021
1022 1022 # Changed so an instance can just be called as VerboseTB_inst() and print
1023 1023 # out the right info on its own.
1024 1024 def __call__(self, etype=None, evalue=None, etb=None):
1025 1025 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1026 1026 if etb is None:
1027 1027 self.handler()
1028 1028 else:
1029 1029 self.handler((etype, evalue, etb))
1030 1030 try:
1031 1031 self.debugger()
1032 1032 except KeyboardInterrupt:
1033 1033 print "\nKeyboardInterrupt"
1034 1034
1035 1035 #----------------------------------------------------------------------------
1036 1036 class FormattedTB(VerboseTB, ListTB):
1037 1037 """Subclass ListTB but allow calling with a traceback.
1038 1038
1039 1039 It can thus be used as a sys.excepthook for Python > 2.1.
1040 1040
1041 1041 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1042 1042
1043 1043 Allows a tb_offset to be specified. This is useful for situations where
1044 1044 one needs to remove a number of topmost frames from the traceback (such as
1045 1045 occurs with python programs that themselves execute other python code,
1046 1046 like Python shells). """
1047 1047
1048 1048 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1049 1049 ostream=None,
1050 1050 tb_offset=0, long_header=False, include_vars=False,
1051 1051 check_cache=None):
1052 1052
1053 1053 # NEVER change the order of this list. Put new modes at the end:
1054 1054 self.valid_modes = ['Plain','Context','Verbose']
1055 1055 self.verbose_modes = self.valid_modes[1:3]
1056 1056
1057 1057 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1058 1058 ostream=ostream, tb_offset=tb_offset,
1059 1059 long_header=long_header, include_vars=include_vars,
1060 1060 check_cache=check_cache)
1061 1061
1062 1062 # Different types of tracebacks are joined with different separators to
1063 1063 # form a single string. They are taken from this dict
1064 1064 self._join_chars = dict(Plain='', Context='\n', Verbose='\n')
1065 1065 # set_mode also sets the tb_join_char attribute
1066 1066 self.set_mode(mode)
1067 1067
1068 1068 def _extract_tb(self,tb):
1069 1069 if tb:
1070 1070 return traceback.extract_tb(tb)
1071 1071 else:
1072 1072 return None
1073 1073
1074 1074 def structured_traceback(self, etype, value, tb, tb_offset=None, context=5):
1075 1075 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1076 1076 mode = self.mode
1077 1077 if mode in self.verbose_modes:
1078 1078 # Verbose modes need a full traceback
1079 1079 return VerboseTB.structured_traceback(
1080 1080 self, etype, value, tb, tb_offset, context
1081 1081 )
1082 1082 else:
1083 1083 # We must check the source cache because otherwise we can print
1084 1084 # out-of-date source code.
1085 1085 self.check_cache()
1086 1086 # Now we can extract and format the exception
1087 1087 elist = self._extract_tb(tb)
1088 1088 return ListTB.structured_traceback(
1089 1089 self, etype, value, elist, tb_offset, context
1090 1090 )
1091 1091
1092 1092 def stb2text(self, stb):
1093 1093 """Convert a structured traceback (a list) to a string."""
1094 1094 return self.tb_join_char.join(stb)
1095 1095
1096 1096
1097 1097 def set_mode(self,mode=None):
1098 1098 """Switch to the desired mode.
1099 1099
1100 1100 If mode is not specified, cycles through the available modes."""
1101 1101
1102 1102 if not mode:
1103 1103 new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \
1104 1104 len(self.valid_modes)
1105 1105 self.mode = self.valid_modes[new_idx]
1106 1106 elif mode not in self.valid_modes:
1107 1107 raise ValueError('Unrecognized mode in FormattedTB: <'+mode+'>\n'
1108 1108 'Valid modes: '+str(self.valid_modes))
1109 1109 else:
1110 1110 self.mode = mode
1111 1111 # include variable details only in 'Verbose' mode
1112 1112 self.include_vars = (self.mode == self.valid_modes[2])
1113 1113 # Set the join character for generating text tracebacks
1114 1114 self.tb_join_char = self._join_chars[self.mode]
1115 1115
1116 1116 # some convenient shorcuts
1117 1117 def plain(self):
1118 1118 self.set_mode(self.valid_modes[0])
1119 1119
1120 1120 def context(self):
1121 1121 self.set_mode(self.valid_modes[1])
1122 1122
1123 1123 def verbose(self):
1124 1124 self.set_mode(self.valid_modes[2])
1125 1125
1126 1126 #----------------------------------------------------------------------------
1127 1127 class AutoFormattedTB(FormattedTB):
1128 1128 """A traceback printer which can be called on the fly.
1129 1129
1130 1130 It will find out about exceptions by itself.
1131 1131
1132 1132 A brief example::
1133 1133
1134 1134 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1135 1135 try:
1136 1136 ...
1137 1137 except:
1138 1138 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1139 1139 """
1140 1140
1141 1141 def __call__(self,etype=None,evalue=None,etb=None,
1142 1142 out=None,tb_offset=None):
1143 1143 """Print out a formatted exception traceback.
1144 1144
1145 1145 Optional arguments:
1146 1146 - out: an open file-like object to direct output to.
1147 1147
1148 1148 - tb_offset: the number of frames to skip over in the stack, on a
1149 1149 per-call basis (this overrides temporarily the instance's tb_offset
1150 1150 given at initialization time. """
1151 1151
1152 1152
1153 1153 if out is None:
1154 1154 out = self.ostream
1155 1155 out.flush()
1156 1156 out.write(self.text(etype, evalue, etb, tb_offset))
1157 1157 out.write('\n')
1158 1158 out.flush()
1159 1159 # FIXME: we should remove the auto pdb behavior from here and leave
1160 1160 # that to the clients.
1161 1161 try:
1162 1162 self.debugger()
1163 1163 except KeyboardInterrupt:
1164 1164 print "\nKeyboardInterrupt"
1165 1165
1166 1166 def structured_traceback(self, etype=None, value=None, tb=None,
1167 1167 tb_offset=None, context=5):
1168 1168 if etype is None:
1169 1169 etype,value,tb = sys.exc_info()
1170 1170 self.tb = tb
1171 1171 return FormattedTB.structured_traceback(
1172 1172 self, etype, value, tb, tb_offset, context)
1173 1173
1174 1174 #---------------------------------------------------------------------------
1175 1175
1176 1176 # A simple class to preserve Nathan's original functionality.
1177 1177 class ColorTB(FormattedTB):
1178 1178 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1179 1179 def __init__(self,color_scheme='Linux',call_pdb=0):
1180 1180 FormattedTB.__init__(self,color_scheme=color_scheme,
1181 1181 call_pdb=call_pdb)
1182 1182
1183 1183
1184 1184 class SyntaxTB(ListTB):
1185 1185 """Extension which holds some state: the last exception value"""
1186 1186
1187 1187 def __init__(self,color_scheme = 'NoColor'):
1188 1188 ListTB.__init__(self,color_scheme)
1189 1189 self.last_syntax_error = None
1190 1190
1191 1191 def __call__(self, etype, value, elist):
1192 1192 self.last_syntax_error = value
1193 1193 ListTB.__call__(self,etype,value,elist)
1194 1194
1195 1195 def clear_err_state(self):
1196 1196 """Return the current error state and clear it"""
1197 1197 e = self.last_syntax_error
1198 1198 self.last_syntax_error = None
1199 1199 return e
1200 1200
1201 1201 def stb2text(self, stb):
1202 1202 """Convert a structured traceback (a list) to a string."""
1203 1203 return ''.join(stb)
1204 1204
1205 1205
1206 1206 #----------------------------------------------------------------------------
1207 1207 # module testing (minimal)
1208 1208 if __name__ == "__main__":
1209 1209 def spam(c, d_e):
1210 1210 (d, e) = d_e
1211 1211 x = c + d
1212 1212 y = c * d
1213 1213 foo(x, y)
1214 1214
1215 1215 def foo(a, b, bar=1):
1216 1216 eggs(a, b + bar)
1217 1217
1218 1218 def eggs(f, g, z=globals()):
1219 1219 h = f + g
1220 1220 i = f - g
1221 1221 return h / i
1222 1222
1223 1223 print ''
1224 1224 print '*** Before ***'
1225 1225 try:
1226 1226 print spam(1, (2, 3))
1227 1227 except:
1228 1228 traceback.print_exc()
1229 1229 print ''
1230 1230
1231 1231 handler = ColorTB()
1232 1232 print '*** ColorTB ***'
1233 1233 try:
1234 1234 print spam(1, (2, 3))
1235 1235 except:
1236 1236 handler(*sys.exc_info())
1237 1237 print ''
1238 1238
1239 1239 handler = VerboseTB()
1240 1240 print '*** VerboseTB ***'
1241 1241 try:
1242 1242 print spam(1, (2, 3))
1243 1243 except:
1244 1244 handler(*sys.exc_info())
1245 1245 print ''
1246 1246
@@ -1,509 +1,509 b''
1 1 """IPython extension to reload modules before executing user code.
2 2
3 3 ``autoreload`` reloads modules automatically before entering the execution of
4 4 code typed at the IPython prompt.
5 5
6 6 This makes for example the following workflow possible:
7 7
8 8 .. sourcecode:: ipython
9 9
10 10 In [1]: %load_ext autoreload
11 11
12 12 In [2]: %autoreload 2
13 13
14 14 In [3]: from foo import some_function
15 15
16 16 In [4]: some_function()
17 17 Out[4]: 42
18 18
19 19 In [5]: # open foo.py in an editor and change some_function to return 43
20 20
21 21 In [6]: some_function()
22 22 Out[6]: 43
23 23
24 24 The module was reloaded without reloading it explicitly, and the object
25 25 imported with ``from foo import ...`` was also updated.
26 26
27 27 Usage
28 28 =====
29 29
30 30 The following magic commands are provided:
31 31
32 32 ``%autoreload``
33 33
34 34 Reload all modules (except those excluded by ``%aimport``)
35 35 automatically now.
36 36
37 37 ``%autoreload 0``
38 38
39 39 Disable automatic reloading.
40 40
41 41 ``%autoreload 1``
42 42
43 43 Reload all modules imported with ``%aimport`` every time before
44 44 executing the Python code typed.
45 45
46 46 ``%autoreload 2``
47 47
48 48 Reload all modules (except those excluded by ``%aimport``) every
49 49 time before executing the Python code typed.
50 50
51 51 ``%aimport``
52 52
53 53 List modules which are to be automatically imported or not to be imported.
54 54
55 55 ``%aimport foo``
56 56
57 57 Import module 'foo' and mark it to be autoreloaded for ``%autoreload 1``
58 58
59 59 ``%aimport -foo``
60 60
61 61 Mark module 'foo' to not be autoreloaded.
62 62
63 63 Caveats
64 64 =======
65 65
66 66 Reloading Python modules in a reliable way is in general difficult,
67 67 and unexpected things may occur. ``%autoreload`` tries to work around
68 68 common pitfalls by replacing function code objects and parts of
69 69 classes previously in the module with new versions. This makes the
70 70 following things to work:
71 71
72 72 - Functions and classes imported via 'from xxx import foo' are upgraded
73 73 to new versions when 'xxx' is reloaded.
74 74
75 75 - Methods and properties of classes are upgraded on reload, so that
76 76 calling 'c.foo()' on an object 'c' created before the reload causes
77 77 the new code for 'foo' to be executed.
78 78
79 79 Some of the known remaining caveats are:
80 80
81 81 - Replacing code objects does not always succeed: changing a @property
82 82 in a class to an ordinary method or a method to a member variable
83 83 can cause problems (but in old objects only).
84 84
85 85 - Functions that are removed (eg. via monkey-patching) from a module
86 86 before it is reloaded are not upgraded.
87 87
88 88 - C extension modules cannot be reloaded, and so cannot be autoreloaded.
89 89 """
90 90 from __future__ import print_function
91 91
92 92 skip_doctest = True
93 93
94 94 #-----------------------------------------------------------------------------
95 95 # Copyright (C) 2000 Thomas Heller
96 96 # Copyright (C) 2008 Pauli Virtanen <pav@iki.fi>
97 97 # Copyright (C) 2012 The IPython Development Team
98 98 #
99 99 # Distributed under the terms of the BSD License. The full license is in
100 100 # the file COPYING, distributed as part of this software.
101 101 #-----------------------------------------------------------------------------
102 102 #
103 103 # This IPython module is written by Pauli Virtanen, based on the autoreload
104 104 # code by Thomas Heller.
105 105
106 106 #-----------------------------------------------------------------------------
107 107 # Imports
108 108 #-----------------------------------------------------------------------------
109 109
110 110 import os
111 111 import sys
112 112 import traceback
113 113 import types
114 114 import weakref
115 115
116 116 try:
117 117 # Reload is not defined by default in Python3.
118 118 reload
119 119 except NameError:
120 120 from imp import reload
121 121
122 from IPython.utils import pyfile
122 from IPython.utils import openpy
123 123 from IPython.utils.py3compat import PY3
124 124
125 125 #------------------------------------------------------------------------------
126 126 # Autoreload functionality
127 127 #------------------------------------------------------------------------------
128 128
129 129 class ModuleReloader(object):
130 130 enabled = False
131 131 """Whether this reloader is enabled"""
132 132
133 133 failed = {}
134 134 """Modules that failed to reload: {module: mtime-on-failed-reload, ...}"""
135 135
136 136 modules = {}
137 137 """Modules specially marked as autoreloadable."""
138 138
139 139 skip_modules = {}
140 140 """Modules specially marked as not autoreloadable."""
141 141
142 142 check_all = True
143 143 """Autoreload all modules, not just those listed in 'modules'"""
144 144
145 145 old_objects = {}
146 146 """(module-name, name) -> weakref, for replacing old code objects"""
147 147
148 148 def mark_module_skipped(self, module_name):
149 149 """Skip reloading the named module in the future"""
150 150 try:
151 151 del self.modules[module_name]
152 152 except KeyError:
153 153 pass
154 154 self.skip_modules[module_name] = True
155 155
156 156 def mark_module_reloadable(self, module_name):
157 157 """Reload the named module in the future (if it is imported)"""
158 158 try:
159 159 del self.skip_modules[module_name]
160 160 except KeyError:
161 161 pass
162 162 self.modules[module_name] = True
163 163
164 164 def aimport_module(self, module_name):
165 165 """Import a module, and mark it reloadable
166 166
167 167 Returns
168 168 -------
169 169 top_module : module
170 170 The imported module if it is top-level, or the top-level
171 171 top_name : module
172 172 Name of top_module
173 173
174 174 """
175 175 self.mark_module_reloadable(module_name)
176 176
177 177 __import__(module_name)
178 178 top_name = module_name.split('.')[0]
179 179 top_module = sys.modules[top_name]
180 180 return top_module, top_name
181 181
182 182 def check(self, check_all=False):
183 183 """Check whether some modules need to be reloaded."""
184 184
185 185 if not self.enabled and not check_all:
186 186 return
187 187
188 188 if check_all or self.check_all:
189 189 modules = sys.modules.keys()
190 190 else:
191 191 modules = self.modules.keys()
192 192
193 193 for modname in modules:
194 194 m = sys.modules.get(modname, None)
195 195
196 196 if modname in self.skip_modules:
197 197 continue
198 198
199 199 if not hasattr(m, '__file__'):
200 200 continue
201 201
202 202 if m.__name__ == '__main__':
203 203 # we cannot reload(__main__)
204 204 continue
205 205
206 206 filename = m.__file__
207 207 path, ext = os.path.splitext(filename)
208 208
209 209 if ext.lower() == '.py':
210 pyc_filename = pyfile.cache_from_source(filename)
210 pyc_filename = openpy.cache_from_source(filename)
211 211 py_filename = filename
212 212 else:
213 213 pyc_filename = filename
214 214 try:
215 py_filename = pyfile.source_from_cache(filename)
215 py_filename = openpy.source_from_cache(filename)
216 216 except ValueError:
217 217 continue
218 218
219 219 try:
220 220 pymtime = os.stat(py_filename).st_mtime
221 221 if pymtime <= os.stat(pyc_filename).st_mtime:
222 222 continue
223 223 if self.failed.get(py_filename, None) == pymtime:
224 224 continue
225 225 except OSError:
226 226 continue
227 227
228 228 try:
229 229 superreload(m, reload, self.old_objects)
230 230 if py_filename in self.failed:
231 231 del self.failed[py_filename]
232 232 except:
233 233 print("[autoreload of %s failed: %s]" % (
234 234 modname, traceback.format_exc(1)), file=sys.stderr)
235 235 self.failed[py_filename] = pymtime
236 236
237 237 #------------------------------------------------------------------------------
238 238 # superreload
239 239 #------------------------------------------------------------------------------
240 240
241 241 if PY3:
242 242 func_attrs = ['__code__', '__defaults__', '__doc__',
243 243 '__closure__', '__globals__', '__dict__']
244 244 else:
245 245 func_attrs = ['func_code', 'func_defaults', 'func_doc',
246 246 'func_closure', 'func_globals', 'func_dict']
247 247
248 248
249 249 def update_function(old, new):
250 250 """Upgrade the code object of a function"""
251 251 for name in func_attrs:
252 252 try:
253 253 setattr(old, name, getattr(new, name))
254 254 except (AttributeError, TypeError):
255 255 pass
256 256
257 257
258 258 def update_class(old, new):
259 259 """Replace stuff in the __dict__ of a class, and upgrade
260 260 method code objects"""
261 261 for key in old.__dict__.keys():
262 262 old_obj = getattr(old, key)
263 263
264 264 try:
265 265 new_obj = getattr(new, key)
266 266 except AttributeError:
267 267 # obsolete attribute: remove it
268 268 try:
269 269 delattr(old, key)
270 270 except (AttributeError, TypeError):
271 271 pass
272 272 continue
273 273
274 274 if update_generic(old_obj, new_obj): continue
275 275
276 276 try:
277 277 setattr(old, key, getattr(new, key))
278 278 except (AttributeError, TypeError):
279 279 pass # skip non-writable attributes
280 280
281 281
282 282 def update_property(old, new):
283 283 """Replace get/set/del functions of a property"""
284 284 update_generic(old.fdel, new.fdel)
285 285 update_generic(old.fget, new.fget)
286 286 update_generic(old.fset, new.fset)
287 287
288 288
289 289 def isinstance2(a, b, typ):
290 290 return isinstance(a, typ) and isinstance(b, typ)
291 291
292 292
293 293 UPDATE_RULES = [
294 294 (lambda a, b: isinstance2(a, b, type),
295 295 update_class),
296 296 (lambda a, b: isinstance2(a, b, types.FunctionType),
297 297 update_function),
298 298 (lambda a, b: isinstance2(a, b, property),
299 299 update_property),
300 300 ]
301 301
302 302
303 303 if PY3:
304 304 UPDATE_RULES.extend([(lambda a, b: isinstance2(a, b, types.MethodType),
305 305 lambda a, b: update_function(a.__func__, b.__func__)),
306 306 ])
307 307 else:
308 308 UPDATE_RULES.extend([(lambda a, b: isinstance2(a, b, types.ClassType),
309 309 update_class),
310 310 (lambda a, b: isinstance2(a, b, types.MethodType),
311 311 lambda a, b: update_function(a.im_func, b.im_func)),
312 312 ])
313 313
314 314
315 315 def update_generic(a, b):
316 316 for type_check, update in UPDATE_RULES:
317 317 if type_check(a, b):
318 318 update(a, b)
319 319 return True
320 320 return False
321 321
322 322
323 323 class StrongRef(object):
324 324 def __init__(self, obj):
325 325 self.obj = obj
326 326 def __call__(self):
327 327 return self.obj
328 328
329 329
330 330 def superreload(module, reload=reload, old_objects={}):
331 331 """Enhanced version of the builtin reload function.
332 332
333 333 superreload remembers objects previously in the module, and
334 334
335 335 - upgrades the class dictionary of every old class in the module
336 336 - upgrades the code object of every old function and method
337 337 - clears the module's namespace before reloading
338 338
339 339 """
340 340
341 341 # collect old objects in the module
342 342 for name, obj in module.__dict__.items():
343 343 if not hasattr(obj, '__module__') or obj.__module__ != module.__name__:
344 344 continue
345 345 key = (module.__name__, name)
346 346 try:
347 347 old_objects.setdefault(key, []).append(weakref.ref(obj))
348 348 except TypeError:
349 349 # weakref doesn't work for all types;
350 350 # create strong references for 'important' cases
351 351 if not PY3 and isinstance(obj, types.ClassType):
352 352 old_objects.setdefault(key, []).append(StrongRef(obj))
353 353
354 354 # reload module
355 355 try:
356 356 # clear namespace first from old cruft
357 357 old_dict = module.__dict__.copy()
358 358 old_name = module.__name__
359 359 module.__dict__.clear()
360 360 module.__dict__['__name__'] = old_name
361 361 module.__dict__['__loader__'] = old_dict['__loader__']
362 362 except (TypeError, AttributeError, KeyError):
363 363 pass
364 364
365 365 try:
366 366 module = reload(module)
367 367 except:
368 368 # restore module dictionary on failed reload
369 369 module.__dict__.update(old_dict)
370 370 raise
371 371
372 372 # iterate over all objects and update functions & classes
373 373 for name, new_obj in module.__dict__.items():
374 374 key = (module.__name__, name)
375 375 if key not in old_objects: continue
376 376
377 377 new_refs = []
378 378 for old_ref in old_objects[key]:
379 379 old_obj = old_ref()
380 380 if old_obj is None: continue
381 381 new_refs.append(old_ref)
382 382 update_generic(old_obj, new_obj)
383 383
384 384 if new_refs:
385 385 old_objects[key] = new_refs
386 386 else:
387 387 del old_objects[key]
388 388
389 389 return module
390 390
391 391 #------------------------------------------------------------------------------
392 392 # IPython connectivity
393 393 #------------------------------------------------------------------------------
394 394
395 395 from IPython.core.hooks import TryNext
396 396 from IPython.core.magic import Magics, magics_class, line_magic
397 397
398 398 @magics_class
399 399 class AutoreloadMagics(Magics):
400 400 def __init__(self, *a, **kw):
401 401 super(AutoreloadMagics, self).__init__(*a, **kw)
402 402 self._reloader = ModuleReloader()
403 403 self._reloader.check_all = False
404 404
405 405 @line_magic
406 406 def autoreload(self, parameter_s=''):
407 407 r"""%autoreload => Reload modules automatically
408 408
409 409 %autoreload
410 410 Reload all modules (except those excluded by %aimport) automatically
411 411 now.
412 412
413 413 %autoreload 0
414 414 Disable automatic reloading.
415 415
416 416 %autoreload 1
417 417 Reload all modules imported with %aimport every time before executing
418 418 the Python code typed.
419 419
420 420 %autoreload 2
421 421 Reload all modules (except those excluded by %aimport) every time
422 422 before executing the Python code typed.
423 423
424 424 Reloading Python modules in a reliable way is in general
425 425 difficult, and unexpected things may occur. %autoreload tries to
426 426 work around common pitfalls by replacing function code objects and
427 427 parts of classes previously in the module with new versions. This
428 428 makes the following things to work:
429 429
430 430 - Functions and classes imported via 'from xxx import foo' are upgraded
431 431 to new versions when 'xxx' is reloaded.
432 432
433 433 - Methods and properties of classes are upgraded on reload, so that
434 434 calling 'c.foo()' on an object 'c' created before the reload causes
435 435 the new code for 'foo' to be executed.
436 436
437 437 Some of the known remaining caveats are:
438 438
439 439 - Replacing code objects does not always succeed: changing a @property
440 440 in a class to an ordinary method or a method to a member variable
441 441 can cause problems (but in old objects only).
442 442
443 443 - Functions that are removed (eg. via monkey-patching) from a module
444 444 before it is reloaded are not upgraded.
445 445
446 446 - C extension modules cannot be reloaded, and so cannot be
447 447 autoreloaded.
448 448
449 449 """
450 450 if parameter_s == '':
451 451 self._reloader.check(True)
452 452 elif parameter_s == '0':
453 453 self._reloader.enabled = False
454 454 elif parameter_s == '1':
455 455 self._reloader.check_all = False
456 456 self._reloader.enabled = True
457 457 elif parameter_s == '2':
458 458 self._reloader.check_all = True
459 459 self._reloader.enabled = True
460 460
461 461 @line_magic
462 462 def aimport(self, parameter_s='', stream=None):
463 463 """%aimport => Import modules for automatic reloading.
464 464
465 465 %aimport
466 466 List modules to automatically import and not to import.
467 467
468 468 %aimport foo
469 469 Import module 'foo' and mark it to be autoreloaded for %autoreload 1
470 470
471 471 %aimport -foo
472 472 Mark module 'foo' to not be autoreloaded for %autoreload 1
473 473 """
474 474 modname = parameter_s
475 475 if not modname:
476 476 to_reload = self._reloader.modules.keys()
477 477 to_reload.sort()
478 478 to_skip = self._reloader.skip_modules.keys()
479 479 to_skip.sort()
480 480 if stream is None:
481 481 stream = sys.stdout
482 482 if self._reloader.check_all:
483 483 stream.write("Modules to reload:\nall-except-skipped\n")
484 484 else:
485 485 stream.write("Modules to reload:\n%s\n" % ' '.join(to_reload))
486 486 stream.write("\nModules to skip:\n%s\n" % ' '.join(to_skip))
487 487 elif modname.startswith('-'):
488 488 modname = modname[1:]
489 489 self._reloader.mark_module_skipped(modname)
490 490 else:
491 491 top_module, top_name = self._reloader.aimport_module(modname)
492 492
493 493 # Inject module to user namespace
494 494 self.shell.push({top_name: top_module})
495 495
496 496 def pre_run_code_hook(self, ip):
497 497 if not self._reloader.enabled:
498 498 raise TryNext
499 499 try:
500 500 self._reloader.check()
501 501 except:
502 502 pass
503 503
504 504
505 505 def load_ipython_extension(ip):
506 506 """Load the extension in IPython."""
507 507 auto_reload = AutoreloadMagics(ip)
508 508 ip.register_magics(auto_reload)
509 509 ip.set_hook('pre_run_code_hook', auto_reload.pre_run_code_hook)
@@ -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,197 +1,198 b''
1 1 """Posix-specific implementation of process utilities.
2 2
3 3 This file is only meant to be imported by process.py, not by end-users.
4 4 """
5 5
6 6 #-----------------------------------------------------------------------------
7 7 # Copyright (C) 2010-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
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16 from __future__ import print_function
17 17
18 18 # Stdlib
19 19 import subprocess as sp
20 20 import sys
21 21
22 22 from IPython.external import pexpect
23 23
24 24 # Our own
25 from .autoattr import auto_attr
26 25 from ._process_common import getoutput, arg_split
27 26 from IPython.utils import py3compat
28 27 from IPython.utils.encoding import DEFAULT_ENCODING
29 28
30 29 #-----------------------------------------------------------------------------
31 30 # Function definitions
32 31 #-----------------------------------------------------------------------------
33 32
34 33 def _find_cmd(cmd):
35 34 """Find the full path to a command using which."""
36 35
37 36 path = sp.Popen(['/usr/bin/env', 'which', cmd],
38 37 stdout=sp.PIPE, stderr=sp.PIPE).communicate()[0]
39 38 return py3compat.bytes_to_str(path)
40 39
41 40
42 41 class ProcessHandler(object):
43 42 """Execute subprocesses under the control of pexpect.
44 43 """
45 44 # Timeout in seconds to wait on each reading of the subprocess' output.
46 45 # This should not be set too low to avoid cpu overusage from our side,
47 46 # since we read in a loop whose period is controlled by this timeout.
48 47 read_timeout = 0.05
49 48
50 49 # Timeout to give a process if we receive SIGINT, between sending the
51 50 # SIGINT to the process and forcefully terminating it.
52 51 terminate_timeout = 0.2
53 52
54 53 # File object where stdout and stderr of the subprocess will be written
55 54 logfile = None
56 55
57 56 # Shell to call for subprocesses to execute
58 sh = None
57 _sh = None
59 58
60 @auto_attr
59 @property
61 60 def sh(self):
62 sh = pexpect.which('sh')
63 if sh is None:
64 raise OSError('"sh" shell not found')
65 return sh
61 if self._sh is None:
62 self._sh = pexpect.which('sh')
63 if self._sh is None:
64 raise OSError('"sh" shell not found')
65
66 return self._sh
66 67
67 68 def __init__(self, logfile=None, read_timeout=None, terminate_timeout=None):
68 69 """Arguments are used for pexpect calls."""
69 70 self.read_timeout = (ProcessHandler.read_timeout if read_timeout is
70 71 None else read_timeout)
71 72 self.terminate_timeout = (ProcessHandler.terminate_timeout if
72 73 terminate_timeout is None else
73 74 terminate_timeout)
74 75 self.logfile = sys.stdout if logfile is None else logfile
75 76
76 77 def getoutput(self, cmd):
77 78 """Run a command and return its stdout/stderr as a string.
78 79
79 80 Parameters
80 81 ----------
81 82 cmd : str
82 83 A command to be executed in the system shell.
83 84
84 85 Returns
85 86 -------
86 87 output : str
87 88 A string containing the combination of stdout and stderr from the
88 89 subprocess, in whatever order the subprocess originally wrote to its
89 90 file descriptors (so the order of the information in this string is the
90 91 correct order as would be seen if running the command in a terminal).
91 92 """
92 93 try:
93 94 return pexpect.run(self.sh, args=['-c', cmd]).replace('\r\n', '\n')
94 95 except KeyboardInterrupt:
95 96 print('^C', file=sys.stderr, end='')
96 97
97 98 def getoutput_pexpect(self, cmd):
98 99 """Run a command and return its stdout/stderr as a string.
99 100
100 101 Parameters
101 102 ----------
102 103 cmd : str
103 104 A command to be executed in the system shell.
104 105
105 106 Returns
106 107 -------
107 108 output : str
108 109 A string containing the combination of stdout and stderr from the
109 110 subprocess, in whatever order the subprocess originally wrote to its
110 111 file descriptors (so the order of the information in this string is the
111 112 correct order as would be seen if running the command in a terminal).
112 113 """
113 114 try:
114 115 return pexpect.run(self.sh, args=['-c', cmd]).replace('\r\n', '\n')
115 116 except KeyboardInterrupt:
116 117 print('^C', file=sys.stderr, end='')
117 118
118 119 def system(self, cmd):
119 120 """Execute a command in a subshell.
120 121
121 122 Parameters
122 123 ----------
123 124 cmd : str
124 125 A command to be executed in the system shell.
125 126
126 127 Returns
127 128 -------
128 129 int : child's exitstatus
129 130 """
130 131 # Get likely encoding for the output.
131 132 enc = DEFAULT_ENCODING
132 133
133 134 # Patterns to match on the output, for pexpect. We read input and
134 135 # allow either a short timeout or EOF
135 136 patterns = [pexpect.TIMEOUT, pexpect.EOF]
136 137 # the index of the EOF pattern in the list.
137 138 # even though we know it's 1, this call means we don't have to worry if
138 139 # we change the above list, and forget to change this value:
139 140 EOF_index = patterns.index(pexpect.EOF)
140 141 # The size of the output stored so far in the process output buffer.
141 142 # Since pexpect only appends to this buffer, each time we print we
142 143 # record how far we've printed, so that next time we only print *new*
143 144 # content from the buffer.
144 145 out_size = 0
145 146 try:
146 147 # Since we're not really searching the buffer for text patterns, we
147 148 # can set pexpect's search window to be tiny and it won't matter.
148 149 # We only search for the 'patterns' timeout or EOF, which aren't in
149 150 # the text itself.
150 151 #child = pexpect.spawn(pcmd, searchwindowsize=1)
151 152 if hasattr(pexpect, 'spawnb'):
152 153 child = pexpect.spawnb(self.sh, args=['-c', cmd]) # Pexpect-U
153 154 else:
154 155 child = pexpect.spawn(self.sh, args=['-c', cmd]) # Vanilla Pexpect
155 156 flush = sys.stdout.flush
156 157 while True:
157 158 # res is the index of the pattern that caused the match, so we
158 159 # know whether we've finished (if we matched EOF) or not
159 160 res_idx = child.expect_list(patterns, self.read_timeout)
160 161 print(child.before[out_size:].decode(enc, 'replace'), end='')
161 162 flush()
162 163 if res_idx==EOF_index:
163 164 break
164 165 # Update the pointer to what we've already printed
165 166 out_size = len(child.before)
166 167 except KeyboardInterrupt:
167 168 # We need to send ^C to the process. The ascii code for '^C' is 3
168 169 # (the character is known as ETX for 'End of Text', see
169 170 # curses.ascii.ETX).
170 171 child.sendline(chr(3))
171 172 # Read and print any more output the program might produce on its
172 173 # way out.
173 174 try:
174 175 out_size = len(child.before)
175 176 child.expect_list(patterns, self.terminate_timeout)
176 177 print(child.before[out_size:].decode(enc, 'replace'), end='')
177 178 sys.stdout.flush()
178 179 except KeyboardInterrupt:
179 180 # Impatient users tend to type it multiple times
180 181 pass
181 182 finally:
182 183 # Ensure the subprocess really is terminated
183 184 child.terminate(force=True)
184 185 # add isalive check, to ensure exitstatus is set:
185 186 child.isalive()
186 187 return child.exitstatus
187 188
188 189
189 190 # Make system() with a functional interface for outside use. Note that we use
190 191 # getoutput() from the _common utils, which is built on top of popen(). Using
191 192 # pexpect to get subprocess output produces difficult to parse output, since
192 193 # programs think they are talking to a tty and produce highly formatted output
193 194 # (ls is a good example) that makes them hard.
194 195 system = ProcessHandler().system
195 196
196 197
197 198
@@ -1,96 +1,35 b''
1 1 # encoding: utf-8
2 2 """Utilities for working with data structures like lists, dicts and tuples.
3 3 """
4 4
5 5 #-----------------------------------------------------------------------------
6 6 # Copyright (C) 2008-2011 The IPython Development Team
7 7 #
8 8 # Distributed under the terms of the BSD License. The full license is in
9 9 # the file COPYING, distributed as part of this software.
10 10 #-----------------------------------------------------------------------------
11 11
12 #-----------------------------------------------------------------------------
13 # Imports
14 #-----------------------------------------------------------------------------
15
16 import types
17
18 #-----------------------------------------------------------------------------
19 # Code
20 #-----------------------------------------------------------------------------
21
22 12 def uniq_stable(elems):
23 13 """uniq_stable(elems) -> list
24 14
25 15 Return from an iterable, a list of all the unique elements in the input,
26 16 but maintaining the order in which they first appear.
27 17
28 18 Note: All elements in the input must be hashable for this routine
29 19 to work, as it internally uses a set for efficiency reasons.
30 20 """
31 21 seen = set()
32 22 return [x for x in elems if x not in seen and not seen.add(x)]
33 23
34 24
35 def sort_compare(lst1, lst2, inplace=1):
36 """Sort and compare two lists.
37
38 By default it does it in place, thus modifying the lists. Use inplace = 0
39 to avoid that (at the cost of temporary copy creation)."""
40 if not inplace:
41 lst1 = lst1[:]
42 lst2 = lst2[:]
43 lst1.sort(); lst2.sort()
44 return lst1 == lst2
45
46
47 def list2dict(lst):
48 """Takes a list of (key,value) pairs and turns it into a dict."""
49
50 dic = {}
51 for k,v in lst: dic[k] = v
52 return dic
53
54
55 def list2dict2(lst, default=''):
56 """Takes a list and turns it into a dict.
57 Much slower than list2dict, but more versatile. This version can take
58 lists with sublists of arbitrary length (including sclars)."""
59
60 dic = {}
61 for elem in lst:
62 if type(elem) in (types.ListType,types.TupleType):
63 size = len(elem)
64 if size == 0:
65 pass
66 elif size == 1:
67 dic[elem] = default
68 else:
69 k,v = elem[0], elem[1:]
70 if len(v) == 1: v = v[0]
71 dic[k] = v
72 else:
73 dic[elem] = default
74 return dic
75
76
77 25 def flatten(seq):
78 26 """Flatten a list of lists (NOT recursive, only works for 2d lists)."""
79 27
80 28 return [x for subseq in seq for x in subseq]
81
82
83 def get_slice(seq, start=0, stop=None, step=1):
84 """Get a slice of a sequence with variable step. Specify start,stop,step."""
85 if stop == None:
86 stop = len(seq)
87 item = lambda i: seq[i]
88 return map(item,xrange(start,stop,step))
89
29
90 30
91 31 def chop(seq, size):
92 32 """Chop a sequence into chunks of the given size."""
93 chunk = lambda i: seq[i:i+size]
94 return map(chunk,xrange(0,len(seq),size))
33 return [seq[i:i+size] for i in xrange(0,len(seq),size)]
95 34
96 35
@@ -1,384 +1,288 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 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
174 """Take multiple lines of input.
175
176 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
178 terminate via EOF (^D in Unix, ^Z-RET in Windows).
179
180 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
182 lines with \\). This allows entering very long strings which are still
183 meant to be treated as single entities.
184 """
185
186 try:
187 if header:
188 header += '\n'
189 lines = [raw_input(header + ps1)]
190 except EOFError:
191 return []
192 terminate = [terminate_str]
193 try:
194 while lines[-1:] != terminate:
195 new_line = raw_input(ps1)
196 while new_line.endswith('\\'):
197 new_line = new_line[:-1] + raw_input(ps2)
198 lines.append(new_line)
199
200 return lines[:-1] # don't return the termination command
201 except EOFError:
202 print()
203 return lines
204
205
206 def raw_input_ext(prompt='', ps2='... '):
207 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
208
209 line = raw_input(prompt)
210 while line.endswith('\\'):
211 line = line[:-1] + raw_input(ps2)
212 return line
213
214
215 157 def ask_yes_no(prompt,default=None):
216 158 """Asks a question and returns a boolean (y/n) answer.
217 159
218 160 If default is given (one of 'y','n'), it is used if the user input is
219 161 empty. Otherwise the question is repeated until an answer is given.
220 162
221 163 An EOF is treated as the default answer. If there is no default, an
222 164 exception is raised to prevent infinite loops.
223 165
224 166 Valid answers are: y/yes/n/no (match is not case sensitive)."""
225 167
226 168 answers = {'y':True,'n':False,'yes':True,'no':False}
227 169 ans = None
228 170 while ans not in answers.keys():
229 171 try:
230 172 ans = raw_input(prompt+' ').lower()
231 173 if not ans: # response was an empty string
232 174 ans = default
233 175 except KeyboardInterrupt:
234 176 pass
235 177 except EOFError:
236 178 if default in answers.keys():
237 179 ans = default
238 180 print()
239 181 else:
240 182 raise
241 183
242 184 return answers[ans]
243 185
244 186
245 class NLprinter:
246 """Print an arbitrarily nested list, indicating index numbers.
247
248 An instance of this class called nlprint is available and callable as a
249 function.
250
251 nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent'
252 and using 'sep' to separate the index from the value. """
253
254 def __init__(self):
255 self.depth = 0
256
257 def __call__(self,lst,pos='',**kw):
258 """Prints the nested list numbering levels."""
259 kw.setdefault('indent',' ')
260 kw.setdefault('sep',': ')
261 kw.setdefault('start',0)
262 kw.setdefault('stop',len(lst))
263 # we need to remove start and stop from kw so they don't propagate
264 # into a recursive call for a nested list.
265 start = kw['start']; del kw['start']
266 stop = kw['stop']; del kw['stop']
267 if self.depth == 0 and 'header' in kw.keys():
268 print(kw['header'])
269
270 for idx in range(start,stop):
271 elem = lst[idx]
272 newpos = pos + str(idx)
273 if type(elem)==type([]):
274 self.depth += 1
275 self.__call__(elem, newpos+",", **kw)
276 self.depth -= 1
277 else:
278 print(kw['indent']*self.depth + newpos + kw["sep"] + repr(elem))
279
280 nlprint = NLprinter()
281
282
283 187 def temp_pyfile(src, ext='.py'):
284 188 """Make a temporary python file, return filename and filehandle.
285 189
286 190 Parameters
287 191 ----------
288 192 src : string or list of strings (no need for ending newlines if list)
289 193 Source code to be written to the file.
290 194
291 195 ext : optional, string
292 196 Extension for the generated file.
293 197
294 198 Returns
295 199 -------
296 200 (filename, open filehandle)
297 201 It is the caller's responsibility to close the open file and unlink it.
298 202 """
299 203 fname = tempfile.mkstemp(ext)[1]
300 204 f = open(fname,'w')
301 205 f.write(src)
302 206 f.flush()
303 207 return fname, f
304 208
305 209
306 210 def raw_print(*args, **kw):
307 211 """Raw print to sys.__stdout__, otherwise identical interface to print()."""
308 212
309 213 print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
310 214 file=sys.__stdout__)
311 215 sys.__stdout__.flush()
312 216
313 217
314 218 def raw_print_err(*args, **kw):
315 219 """Raw print to sys.__stderr__, otherwise identical interface to print()."""
316 220
317 221 print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
318 222 file=sys.__stderr__)
319 223 sys.__stderr__.flush()
320 224
321 225
322 226 # Short aliases for quick debugging, do NOT use these in production code.
323 227 rprint = raw_print
324 228 rprinte = raw_print_err
325 229
326 230
327 231 class CapturedIO(object):
328 232 """Simple object for containing captured stdout/err StringIO objects"""
329 233
330 234 def __init__(self, stdout, stderr):
331 235 self._stdout = stdout
332 236 self._stderr = stderr
333 237
334 238 def __str__(self):
335 239 return self.stdout
336 240
337 241 @property
338 242 def stdout(self):
339 243 if not self._stdout:
340 244 return ''
341 245 return self._stdout.getvalue()
342 246
343 247 @property
344 248 def stderr(self):
345 249 if not self._stderr:
346 250 return ''
347 251 return self._stderr.getvalue()
348 252
349 253 def show(self):
350 254 """write my output to sys.stdout/err as appropriate"""
351 255 sys.stdout.write(self.stdout)
352 256 sys.stderr.write(self.stderr)
353 257 sys.stdout.flush()
354 258 sys.stderr.flush()
355 259
356 260 __call__ = show
357 261
358 262
359 263 class capture_output(object):
360 264 """context manager for capturing stdout/err"""
361 265 stdout = True
362 266 stderr = True
363 267
364 268 def __init__(self, stdout=True, stderr=True):
365 269 self.stdout = stdout
366 270 self.stderr = stderr
367 271
368 272 def __enter__(self):
369 273 self.sys_stdout = sys.stdout
370 274 self.sys_stderr = sys.stderr
371 275
372 276 stdout = stderr = False
373 277 if self.stdout:
374 278 stdout = sys.stdout = StringIO()
375 279 if self.stderr:
376 280 stderr = sys.stderr = StringIO()
377 281
378 282 return CapturedIO(stdout, stderr)
379 283
380 284 def __exit__(self, exc_type, exc_value, traceback):
381 285 sys.stdout = self.sys_stdout
382 286 sys.stderr = self.sys_stderr
383 287
384 288
@@ -1,393 +1,391 b''
1 1 # encoding: utf-8
2 2 """A dict subclass that supports attribute style access.
3 3
4 4 Authors:
5 5
6 6 * Fernando Perez (original)
7 7 * Brian Granger (refactoring to a dict subclass)
8 8 """
9 9
10 10 #-----------------------------------------------------------------------------
11 11 # Copyright (C) 2008-2011 The IPython Development Team
12 12 #
13 13 # Distributed under the terms of the BSD License. The full license is in
14 14 # the file COPYING, distributed as part of this software.
15 15 #-----------------------------------------------------------------------------
16 16
17 17 #-----------------------------------------------------------------------------
18 18 # Imports
19 19 #-----------------------------------------------------------------------------
20 20
21 from IPython.utils.data import list2dict2
22
23 21 __all__ = ['Struct']
24 22
25 23 #-----------------------------------------------------------------------------
26 24 # Code
27 25 #-----------------------------------------------------------------------------
28 26
29 27
30 28 class Struct(dict):
31 29 """A dict subclass with attribute style access.
32 30
33 31 This dict subclass has a a few extra features:
34 32
35 33 * Attribute style access.
36 34 * Protection of class members (like keys, items) when using attribute
37 35 style access.
38 36 * The ability to restrict assignment to only existing keys.
39 37 * Intelligent merging.
40 38 * Overloaded operators.
41 39 """
42 40 _allownew = True
43 41 def __init__(self, *args, **kw):
44 42 """Initialize with a dictionary, another Struct, or data.
45 43
46 44 Parameters
47 45 ----------
48 46 args : dict, Struct
49 47 Initialize with one dict or Struct
50 48 kw : dict
51 49 Initialize with key, value pairs.
52 50
53 51 Examples
54 52 --------
55 53
56 54 >>> s = Struct(a=10,b=30)
57 55 >>> s.a
58 56 10
59 57 >>> s.b
60 58 30
61 59 >>> s2 = Struct(s,c=30)
62 60 >>> sorted(s2.keys())
63 61 ['a', 'b', 'c']
64 62 """
65 63 object.__setattr__(self, '_allownew', True)
66 64 dict.__init__(self, *args, **kw)
67 65
68 66 def __setitem__(self, key, value):
69 67 """Set an item with check for allownew.
70 68
71 69 Examples
72 70 --------
73 71
74 72 >>> s = Struct()
75 73 >>> s['a'] = 10
76 74 >>> s.allow_new_attr(False)
77 75 >>> s['a'] = 10
78 76 >>> s['a']
79 77 10
80 78 >>> try:
81 79 ... s['b'] = 20
82 80 ... except KeyError:
83 81 ... print 'this is not allowed'
84 82 ...
85 83 this is not allowed
86 84 """
87 85 if not self._allownew and key not in self:
88 86 raise KeyError(
89 87 "can't create new attribute %s when allow_new_attr(False)" % key)
90 88 dict.__setitem__(self, key, value)
91 89
92 90 def __setattr__(self, key, value):
93 91 """Set an attr with protection of class members.
94 92
95 93 This calls :meth:`self.__setitem__` but convert :exc:`KeyError` to
96 94 :exc:`AttributeError`.
97 95
98 96 Examples
99 97 --------
100 98
101 99 >>> s = Struct()
102 100 >>> s.a = 10
103 101 >>> s.a
104 102 10
105 103 >>> try:
106 104 ... s.get = 10
107 105 ... except AttributeError:
108 106 ... print "you can't set a class member"
109 107 ...
110 108 you can't set a class member
111 109 """
112 110 # If key is an str it might be a class member or instance var
113 111 if isinstance(key, str):
114 112 # I can't simply call hasattr here because it calls getattr, which
115 113 # calls self.__getattr__, which returns True for keys in
116 114 # self._data. But I only want keys in the class and in
117 115 # self.__dict__
118 116 if key in self.__dict__ or hasattr(Struct, key):
119 117 raise AttributeError(
120 118 'attr %s is a protected member of class Struct.' % key
121 119 )
122 120 try:
123 121 self.__setitem__(key, value)
124 122 except KeyError as e:
125 123 raise AttributeError(e)
126 124
127 125 def __getattr__(self, key):
128 126 """Get an attr by calling :meth:`dict.__getitem__`.
129 127
130 128 Like :meth:`__setattr__`, this method converts :exc:`KeyError` to
131 129 :exc:`AttributeError`.
132 130
133 131 Examples
134 132 --------
135 133
136 134 >>> s = Struct(a=10)
137 135 >>> s.a
138 136 10
139 137 >>> type(s.get)
140 138 <... 'builtin_function_or_method'>
141 139 >>> try:
142 140 ... s.b
143 141 ... except AttributeError:
144 142 ... print "I don't have that key"
145 143 ...
146 144 I don't have that key
147 145 """
148 146 try:
149 147 result = self[key]
150 148 except KeyError:
151 149 raise AttributeError(key)
152 150 else:
153 151 return result
154 152
155 153 def __iadd__(self, other):
156 154 """s += s2 is a shorthand for s.merge(s2).
157 155
158 156 Examples
159 157 --------
160 158
161 159 >>> s = Struct(a=10,b=30)
162 160 >>> s2 = Struct(a=20,c=40)
163 161 >>> s += s2
164 162 >>> sorted(s.keys())
165 163 ['a', 'b', 'c']
166 164 """
167 165 self.merge(other)
168 166 return self
169 167
170 168 def __add__(self,other):
171 169 """s + s2 -> New Struct made from s.merge(s2).
172 170
173 171 Examples
174 172 --------
175 173
176 174 >>> s1 = Struct(a=10,b=30)
177 175 >>> s2 = Struct(a=20,c=40)
178 176 >>> s = s1 + s2
179 177 >>> sorted(s.keys())
180 178 ['a', 'b', 'c']
181 179 """
182 180 sout = self.copy()
183 181 sout.merge(other)
184 182 return sout
185 183
186 184 def __sub__(self,other):
187 185 """s1 - s2 -> remove keys in s2 from s1.
188 186
189 187 Examples
190 188 --------
191 189
192 190 >>> s1 = Struct(a=10,b=30)
193 191 >>> s2 = Struct(a=40)
194 192 >>> s = s1 - s2
195 193 >>> s
196 194 {'b': 30}
197 195 """
198 196 sout = self.copy()
199 197 sout -= other
200 198 return sout
201 199
202 200 def __isub__(self,other):
203 201 """Inplace remove keys from self that are in other.
204 202
205 203 Examples
206 204 --------
207 205
208 206 >>> s1 = Struct(a=10,b=30)
209 207 >>> s2 = Struct(a=40)
210 208 >>> s1 -= s2
211 209 >>> s1
212 210 {'b': 30}
213 211 """
214 212 for k in other.keys():
215 213 if k in self:
216 214 del self[k]
217 215 return self
218 216
219 217 def __dict_invert(self, data):
220 218 """Helper function for merge.
221 219
222 220 Takes a dictionary whose values are lists and returns a dict with
223 221 the elements of each list as keys and the original keys as values.
224 222 """
225 223 outdict = {}
226 224 for k,lst in data.items():
227 225 if isinstance(lst, str):
228 226 lst = lst.split()
229 227 for entry in lst:
230 228 outdict[entry] = k
231 229 return outdict
232 230
233 231 def dict(self):
234 232 return self
235 233
236 234 def copy(self):
237 235 """Return a copy as a Struct.
238 236
239 237 Examples
240 238 --------
241 239
242 240 >>> s = Struct(a=10,b=30)
243 241 >>> s2 = s.copy()
244 242 >>> type(s2) is Struct
245 243 True
246 244 """
247 245 return Struct(dict.copy(self))
248 246
249 247 def hasattr(self, key):
250 248 """hasattr function available as a method.
251 249
252 250 Implemented like has_key.
253 251
254 252 Examples
255 253 --------
256 254
257 255 >>> s = Struct(a=10)
258 256 >>> s.hasattr('a')
259 257 True
260 258 >>> s.hasattr('b')
261 259 False
262 260 >>> s.hasattr('get')
263 261 False
264 262 """
265 263 return key in self
266 264
267 265 def allow_new_attr(self, allow = True):
268 266 """Set whether new attributes can be created in this Struct.
269 267
270 268 This can be used to catch typos by verifying that the attribute user
271 269 tries to change already exists in this Struct.
272 270 """
273 271 object.__setattr__(self, '_allownew', allow)
274 272
275 273 def merge(self, __loc_data__=None, __conflict_solve=None, **kw):
276 274 """Merge two Structs with customizable conflict resolution.
277 275
278 276 This is similar to :meth:`update`, but much more flexible. First, a
279 277 dict is made from data+key=value pairs. When merging this dict with
280 278 the Struct S, the optional dictionary 'conflict' is used to decide
281 279 what to do.
282 280
283 281 If conflict is not given, the default behavior is to preserve any keys
284 282 with their current value (the opposite of the :meth:`update` method's
285 283 behavior).
286 284
287 285 Parameters
288 286 ----------
289 287 __loc_data : dict, Struct
290 288 The data to merge into self
291 289 __conflict_solve : dict
292 290 The conflict policy dict. The keys are binary functions used to
293 291 resolve the conflict and the values are lists of strings naming
294 292 the keys the conflict resolution function applies to. Instead of
295 293 a list of strings a space separated string can be used, like
296 294 'a b c'.
297 295 kw : dict
298 296 Additional key, value pairs to merge in
299 297
300 298 Notes
301 299 -----
302 300
303 301 The `__conflict_solve` dict is a dictionary of binary functions which will be used to
304 302 solve key conflicts. Here is an example::
305 303
306 304 __conflict_solve = dict(
307 305 func1=['a','b','c'],
308 306 func2=['d','e']
309 307 )
310 308
311 309 In this case, the function :func:`func1` will be used to resolve
312 310 keys 'a', 'b' and 'c' and the function :func:`func2` will be used for
313 311 keys 'd' and 'e'. This could also be written as::
314 312
315 313 __conflict_solve = dict(func1='a b c',func2='d e')
316 314
317 315 These functions will be called for each key they apply to with the
318 316 form::
319 317
320 318 func1(self['a'], other['a'])
321 319
322 320 The return value is used as the final merged value.
323 321
324 322 As a convenience, merge() provides five (the most commonly needed)
325 323 pre-defined policies: preserve, update, add, add_flip and add_s. The
326 324 easiest explanation is their implementation::
327 325
328 326 preserve = lambda old,new: old
329 327 update = lambda old,new: new
330 328 add = lambda old,new: old + new
331 329 add_flip = lambda old,new: new + old # note change of order!
332 330 add_s = lambda old,new: old + ' ' + new # only for str!
333 331
334 332 You can use those four words (as strings) as keys instead
335 333 of defining them as functions, and the merge method will substitute
336 334 the appropriate functions for you.
337 335
338 336 For more complicated conflict resolution policies, you still need to
339 337 construct your own functions.
340 338
341 339 Examples
342 340 --------
343 341
344 342 This show the default policy:
345 343
346 344 >>> s = Struct(a=10,b=30)
347 345 >>> s2 = Struct(a=20,c=40)
348 346 >>> s.merge(s2)
349 347 >>> sorted(s.items())
350 348 [('a', 10), ('b', 30), ('c', 40)]
351 349
352 350 Now, show how to specify a conflict dict:
353 351
354 352 >>> s = Struct(a=10,b=30)
355 353 >>> s2 = Struct(a=20,b=40)
356 354 >>> conflict = {'update':'a','add':'b'}
357 355 >>> s.merge(s2,conflict)
358 356 >>> sorted(s.items())
359 357 [('a', 20), ('b', 70)]
360 358 """
361 359
362 360 data_dict = dict(__loc_data__,**kw)
363 361
364 362 # policies for conflict resolution: two argument functions which return
365 363 # the value that will go in the new struct
366 364 preserve = lambda old,new: old
367 365 update = lambda old,new: new
368 366 add = lambda old,new: old + new
369 367 add_flip = lambda old,new: new + old # note change of order!
370 368 add_s = lambda old,new: old + ' ' + new
371 369
372 370 # default policy is to keep current keys when there's a conflict
373 conflict_solve = list2dict2(self.keys(), default = preserve)
371 conflict_solve = dict.fromkeys(self, preserve)
374 372
375 373 # the conflict_solve dictionary is given by the user 'inverted': we
376 374 # need a name-function mapping, it comes as a function -> names
377 375 # dict. Make a local copy (b/c we'll make changes), replace user
378 376 # strings for the three builtin policies and invert it.
379 377 if __conflict_solve:
380 378 inv_conflict_solve_user = __conflict_solve.copy()
381 379 for name, func in [('preserve',preserve), ('update',update),
382 380 ('add',add), ('add_flip',add_flip),
383 381 ('add_s',add_s)]:
384 382 if name in inv_conflict_solve_user.keys():
385 383 inv_conflict_solve_user[func] = inv_conflict_solve_user[name]
386 384 del inv_conflict_solve_user[name]
387 385 conflict_solve.update(self.__dict_invert(inv_conflict_solve_user))
388 386 for key in data_dict:
389 387 if key not in self:
390 388 self[key] = data_dict[key]
391 389 else:
392 390 self[key] = conflict_solve[key](self[key],data_dict[key])
393 391
@@ -1,219 +1,239 b''
1 1 """
2 2 Tools to open .py files as Unicode, using the encoding specified within the file,
3 3 as per PEP 263.
4 4
5 5 Much of the code is taken from the tokenize module in Python 3.2.
6 6 """
7 7 from __future__ import absolute_import
8 8
9 9 import io
10 10 from io import TextIOWrapper, BytesIO
11 import os.path
11 12 import re
12 13
13 14 cookie_re = re.compile(ur"coding[:=]\s*([-\w.]+)", re.UNICODE)
14 15 cookie_comment_re = re.compile(ur"^\s*#.*coding[:=]\s*([-\w.]+)", re.UNICODE)
15 16
16 17 try:
17 18 # Available in Python 3
18 19 from tokenize import detect_encoding
19 20 except ImportError:
20 21 from codecs import lookup, BOM_UTF8
21 22
22 23 # Copied from Python 3.2 tokenize
23 24 def _get_normal_name(orig_enc):
24 25 """Imitates get_normal_name in tokenizer.c."""
25 26 # Only care about the first 12 characters.
26 27 enc = orig_enc[:12].lower().replace("_", "-")
27 28 if enc == "utf-8" or enc.startswith("utf-8-"):
28 29 return "utf-8"
29 30 if enc in ("latin-1", "iso-8859-1", "iso-latin-1") or \
30 31 enc.startswith(("latin-1-", "iso-8859-1-", "iso-latin-1-")):
31 32 return "iso-8859-1"
32 33 return orig_enc
33 34
34 35 # Copied from Python 3.2 tokenize
35 36 def detect_encoding(readline):
36 37 """
37 38 The detect_encoding() function is used to detect the encoding that should
38 39 be used to decode a Python source file. It requires one argment, readline,
39 40 in the same way as the tokenize() generator.
40 41
41 42 It will call readline a maximum of twice, and return the encoding used
42 43 (as a string) and a list of any lines (left as bytes) it has read in.
43 44
44 45 It detects the encoding from the presence of a utf-8 bom or an encoding
45 46 cookie as specified in pep-0263. If both a bom and a cookie are present,
46 47 but disagree, a SyntaxError will be raised. If the encoding cookie is an
47 48 invalid charset, raise a SyntaxError. Note that if a utf-8 bom is found,
48 49 'utf-8-sig' is returned.
49 50
50 51 If no encoding is specified, then the default of 'utf-8' will be returned.
51 52 """
52 53 bom_found = False
53 54 encoding = None
54 55 default = 'utf-8'
55 56 def read_or_stop():
56 57 try:
57 58 return readline()
58 59 except StopIteration:
59 60 return b''
60 61
61 62 def find_cookie(line):
62 63 try:
63 64 line_string = line.decode('ascii')
64 65 except UnicodeDecodeError:
65 66 return None
66 67
67 68 matches = cookie_re.findall(line_string)
68 69 if not matches:
69 70 return None
70 71 encoding = _get_normal_name(matches[0])
71 72 try:
72 73 codec = lookup(encoding)
73 74 except LookupError:
74 75 # This behaviour mimics the Python interpreter
75 76 raise SyntaxError("unknown encoding: " + encoding)
76 77
77 78 if bom_found:
78 79 if codec.name != 'utf-8':
79 80 # This behaviour mimics the Python interpreter
80 81 raise SyntaxError('encoding problem: utf-8')
81 82 encoding += '-sig'
82 83 return encoding
83 84
84 85 first = read_or_stop()
85 86 if first.startswith(BOM_UTF8):
86 87 bom_found = True
87 88 first = first[3:]
88 89 default = 'utf-8-sig'
89 90 if not first:
90 91 return default, []
91 92
92 93 encoding = find_cookie(first)
93 94 if encoding:
94 95 return encoding, [first]
95 96
96 97 second = read_or_stop()
97 98 if not second:
98 99 return default, [first]
99 100
100 101 encoding = find_cookie(second)
101 102 if encoding:
102 103 return encoding, [first, second]
103 104
104 105 return default, [first, second]
105 106
106 107 try:
107 108 # Available in Python 3.2 and above.
108 109 from tokenize import open
109 110 except ImportError:
110 111 # Copied from Python 3.2 tokenize
111 112 def open(filename):
112 113 """Open a file in read only mode using the encoding detected by
113 114 detect_encoding().
114 115 """
115 116 buffer = io.open(filename, 'rb') # Tweaked to use io.open for Python 2
116 117 encoding, lines = detect_encoding(buffer.readline)
117 118 buffer.seek(0)
118 119 text = TextIOWrapper(buffer, encoding, line_buffering=True)
119 120 text.mode = 'r'
120 121 return text
121 122
122 123 def source_to_unicode(txt, errors='replace', skip_encoding_cookie=True):
123 124 """Converts a bytes string with python source code to unicode.
124 125
125 126 Unicode strings are passed through unchanged. Byte strings are checked
126 127 for the python source file encoding cookie to determine encoding.
127 128 txt can be either a bytes buffer or a string containing the source
128 129 code.
129 130 """
130 131 if isinstance(txt, unicode):
131 132 return txt
132 133 if isinstance(txt, bytes):
133 134 buffer = BytesIO(txt)
134 135 else:
135 136 buffer = txt
136 137 try:
137 138 encoding, _ = detect_encoding(buffer.readline)
138 139 except SyntaxError:
139 140 encoding = "ascii"
140 141 buffer.seek(0)
141 142 text = TextIOWrapper(buffer, encoding, errors=errors, line_buffering=True)
142 143 text.mode = 'r'
143 144 if skip_encoding_cookie:
144 145 return u"".join(strip_encoding_cookie(text))
145 146 else:
146 147 return text.read()
147 148
148 149 def strip_encoding_cookie(filelike):
149 150 """Generator to pull lines from a text-mode file, skipping the encoding
150 151 cookie if it is found in the first two lines.
151 152 """
152 153 it = iter(filelike)
153 154 try:
154 155 first = next(it)
155 156 if not cookie_comment_re.match(first):
156 157 yield first
157 158 second = next(it)
158 159 if not cookie_comment_re.match(second):
159 160 yield second
160 161 except StopIteration:
161 162 return
162 163
163 164 for line in it:
164 165 yield line
165 166
166 167 def read_py_file(filename, skip_encoding_cookie=True):
167 168 """Read a Python file, using the encoding declared inside the file.
168 169
169 170 Parameters
170 171 ----------
171 172 filename : str
172 173 The path to the file to read.
173 174 skip_encoding_cookie : bool
174 175 If True (the default), and the encoding declaration is found in the first
175 176 two lines, that line will be excluded from the output - compiling a
176 177 unicode string with an encoding declaration is a SyntaxError in Python 2.
177 178
178 179 Returns
179 180 -------
180 181 A unicode string containing the contents of the file.
181 182 """
182 183 with open(filename) as f: # the open function defined in this module.
183 184 if skip_encoding_cookie:
184 185 return "".join(strip_encoding_cookie(f))
185 186 else:
186 187 return f.read()
187 188
188 189 def read_py_url(url, errors='replace', skip_encoding_cookie=True):
189 190 """Read a Python file from a URL, using the encoding declared inside the file.
190 191
191 192 Parameters
192 193 ----------
193 194 url : str
194 195 The URL from which to fetch the file.
195 196 errors : str
196 197 How to handle decoding errors in the file. Options are the same as for
197 198 bytes.decode(), but here 'replace' is the default.
198 199 skip_encoding_cookie : bool
199 200 If True (the default), and the encoding declaration is found in the first
200 201 two lines, that line will be excluded from the output - compiling a
201 202 unicode string with an encoding declaration is a SyntaxError in Python 2.
202 203
203 204 Returns
204 205 -------
205 206 A unicode string containing the contents of the file.
206 207 """
207 208 from urllib import urlopen # Deferred import for faster start
208 209 response = urlopen(url)
209 210 buffer = io.BytesIO(response.read())
210 211 return source_to_unicode(buffer, errors, skip_encoding_cookie)
211 212
212 213 def _list_readline(x):
213 214 """Given a list, returns a readline() function that returns the next element
214 215 with each call.
215 216 """
216 217 x = iter(x)
217 218 def readline():
218 219 return next(x)
219 220 return readline
221
222 # Code for going between .py files and cached .pyc files ----------------------
223
224 try: # Python 3.2, see PEP 3147
225 from imp import source_from_cache, cache_from_source
226 except ImportError:
227 # Python <= 3.1: .pyc files go next to .py
228 def source_from_cache(path):
229 basename, ext = os.path.splitext(path)
230 if ext not in ('.pyc', '.pyo'):
231 raise ValueError('Not a cached Python file extension', ext)
232 # Should we look for .pyw files?
233 return basename + '.py'
234
235 def cache_from_source(path, debug_override=None):
236 if debug_override is None:
237 debug_override = __debug__
238 basename, ext = os.path.splitext(path)
239 return basename + '.pyc' if debug_override else '.pyo'
@@ -1,824 +1,717 b''
1 1 # encoding: utf-8
2 2 """
3 3 Utilities for working with strings and text.
4 4
5 5 Inheritance diagram:
6 6
7 7 .. inheritance-diagram:: IPython.utils.text
8 8 :parts: 3
9 9 """
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Copyright (C) 2008-2011 The IPython Development Team
13 13 #
14 14 # Distributed under the terms of the BSD License. The full license is in
15 15 # the file COPYING, distributed as part of this software.
16 16 #-----------------------------------------------------------------------------
17 17
18 18 #-----------------------------------------------------------------------------
19 19 # Imports
20 20 #-----------------------------------------------------------------------------
21 21
22 22 import __main__
23 23
24 24 import os
25 25 import re
26 26 import sys
27 27 import textwrap
28 28 from string import Formatter
29 29
30 30 from IPython.external.path import path
31 31 from IPython.testing.skipdoctest import skip_doctest_py3, skip_doctest
32 32 from IPython.utils import py3compat
33 from IPython.utils.io import nlprint
34 33 from IPython.utils.data import flatten
35 34
36 35 #-----------------------------------------------------------------------------
37 36 # Code
38 37 #-----------------------------------------------------------------------------
39 38
40 def unquote_ends(istr):
41 """Remove a single pair of quotes from the endpoints of a string."""
42
43 if not istr:
44 return istr
45 if (istr[0]=="'" and istr[-1]=="'") or \
46 (istr[0]=='"' and istr[-1]=='"'):
47 return istr[1:-1]
48 else:
49 return istr
50
51
52 39 class LSString(str):
53 40 """String derivative with a special access attributes.
54 41
55 42 These are normal strings, but with the special attributes:
56 43
57 44 .l (or .list) : value as list (split on newlines).
58 45 .n (or .nlstr): original value (the string itself).
59 46 .s (or .spstr): value as whitespace-separated string.
60 47 .p (or .paths): list of path objects
61 48
62 49 Any values which require transformations are computed only once and
63 50 cached.
64 51
65 52 Such strings are very useful to efficiently interact with the shell, which
66 53 typically only understands whitespace-separated options for commands."""
67 54
68 55 def get_list(self):
69 56 try:
70 57 return self.__list
71 58 except AttributeError:
72 59 self.__list = self.split('\n')
73 60 return self.__list
74 61
75 62 l = list = property(get_list)
76 63
77 64 def get_spstr(self):
78 65 try:
79 66 return self.__spstr
80 67 except AttributeError:
81 68 self.__spstr = self.replace('\n',' ')
82 69 return self.__spstr
83 70
84 71 s = spstr = property(get_spstr)
85 72
86 73 def get_nlstr(self):
87 74 return self
88 75
89 76 n = nlstr = property(get_nlstr)
90 77
91 78 def get_paths(self):
92 79 try:
93 80 return self.__paths
94 81 except AttributeError:
95 82 self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)]
96 83 return self.__paths
97 84
98 85 p = paths = property(get_paths)
99 86
100 87 # FIXME: We need to reimplement type specific displayhook and then add this
101 88 # back as a custom printer. This should also be moved outside utils into the
102 89 # core.
103 90
104 91 # def print_lsstring(arg):
105 92 # """ Prettier (non-repr-like) and more informative printer for LSString """
106 93 # print "LSString (.p, .n, .l, .s available). Value:"
107 94 # print arg
108 95 #
109 96 #
110 97 # print_lsstring = result_display.when_type(LSString)(print_lsstring)
111 98
112 99
113 100 class SList(list):
114 101 """List derivative with a special access attributes.
115 102
116 103 These are normal lists, but with the special attributes:
117 104
118 105 .l (or .list) : value as list (the list itself).
119 106 .n (or .nlstr): value as a string, joined on newlines.
120 107 .s (or .spstr): value as a string, joined on spaces.
121 108 .p (or .paths): list of path objects
122 109
123 110 Any values which require transformations are computed only once and
124 111 cached."""
125 112
126 113 def get_list(self):
127 114 return self
128 115
129 116 l = list = property(get_list)
130 117
131 118 def get_spstr(self):
132 119 try:
133 120 return self.__spstr
134 121 except AttributeError:
135 122 self.__spstr = ' '.join(self)
136 123 return self.__spstr
137 124
138 125 s = spstr = property(get_spstr)
139 126
140 127 def get_nlstr(self):
141 128 try:
142 129 return self.__nlstr
143 130 except AttributeError:
144 131 self.__nlstr = '\n'.join(self)
145 132 return self.__nlstr
146 133
147 134 n = nlstr = property(get_nlstr)
148 135
149 136 def get_paths(self):
150 137 try:
151 138 return self.__paths
152 139 except AttributeError:
153 140 self.__paths = [path(p) for p in self if os.path.exists(p)]
154 141 return self.__paths
155 142
156 143 p = paths = property(get_paths)
157 144
158 145 def grep(self, pattern, prune = False, field = None):
159 146 """ Return all strings matching 'pattern' (a regex or callable)
160 147
161 148 This is case-insensitive. If prune is true, return all items
162 149 NOT matching the pattern.
163 150
164 151 If field is specified, the match must occur in the specified
165 152 whitespace-separated field.
166 153
167 154 Examples::
168 155
169 156 a.grep( lambda x: x.startswith('C') )
170 157 a.grep('Cha.*log', prune=1)
171 158 a.grep('chm', field=-1)
172 159 """
173 160
174 161 def match_target(s):
175 162 if field is None:
176 163 return s
177 164 parts = s.split()
178 165 try:
179 166 tgt = parts[field]
180 167 return tgt
181 168 except IndexError:
182 169 return ""
183 170
184 171 if isinstance(pattern, basestring):
185 172 pred = lambda x : re.search(pattern, x, re.IGNORECASE)
186 173 else:
187 174 pred = pattern
188 175 if not prune:
189 176 return SList([el for el in self if pred(match_target(el))])
190 177 else:
191 178 return SList([el for el in self if not pred(match_target(el))])
192 179
193 180 def fields(self, *fields):
194 181 """ Collect whitespace-separated fields from string list
195 182
196 183 Allows quick awk-like usage of string lists.
197 184
198 185 Example data (in var a, created by 'a = !ls -l')::
199 186 -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog
200 187 drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython
201 188
202 189 a.fields(0) is ['-rwxrwxrwx', 'drwxrwxrwx+']
203 190 a.fields(1,0) is ['1 -rwxrwxrwx', '6 drwxrwxrwx+']
204 191 (note the joining by space).
205 192 a.fields(-1) is ['ChangeLog', 'IPython']
206 193
207 194 IndexErrors are ignored.
208 195
209 196 Without args, fields() just split()'s the strings.
210 197 """
211 198 if len(fields) == 0:
212 199 return [el.split() for el in self]
213 200
214 201 res = SList()
215 202 for el in [f.split() for f in self]:
216 203 lineparts = []
217 204
218 205 for fd in fields:
219 206 try:
220 207 lineparts.append(el[fd])
221 208 except IndexError:
222 209 pass
223 210 if lineparts:
224 211 res.append(" ".join(lineparts))
225 212
226 213 return res
227 214
228 215 def sort(self,field= None, nums = False):
229 216 """ sort by specified fields (see fields())
230 217
231 218 Example::
232 219 a.sort(1, nums = True)
233 220
234 221 Sorts a by second field, in numerical order (so that 21 > 3)
235 222
236 223 """
237 224
238 225 #decorate, sort, undecorate
239 226 if field is not None:
240 227 dsu = [[SList([line]).fields(field), line] for line in self]
241 228 else:
242 229 dsu = [[line, line] for line in self]
243 230 if nums:
244 231 for i in range(len(dsu)):
245 232 numstr = "".join([ch for ch in dsu[i][0] if ch.isdigit()])
246 233 try:
247 234 n = int(numstr)
248 235 except ValueError:
249 236 n = 0;
250 237 dsu[i][0] = n
251 238
252 239
253 240 dsu.sort()
254 241 return SList([t[1] for t in dsu])
255 242
256 243
257 244 # FIXME: We need to reimplement type specific displayhook and then add this
258 245 # back as a custom printer. This should also be moved outside utils into the
259 246 # core.
260 247
261 248 # def print_slist(arg):
262 249 # """ Prettier (non-repr-like) and more informative printer for SList """
263 250 # print "SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):"
264 251 # if hasattr(arg, 'hideonce') and arg.hideonce:
265 252 # arg.hideonce = False
266 253 # return
267 254 #
268 # nlprint(arg)
255 # nlprint(arg) # This was a nested list printer, now removed.
269 256 #
270 257 # print_slist = result_display.when_type(SList)(print_slist)
271 258
272 259
273 def esc_quotes(strng):
274 """Return the input string with single and double quotes escaped out"""
275
276 return strng.replace('"','\\"').replace("'","\\'")
277
278
279 def qw(words,flat=0,sep=None,maxsplit=-1):
280 """Similar to Perl's qw() operator, but with some more options.
281
282 qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit)
283
284 words can also be a list itself, and with flat=1, the output will be
285 recursively flattened.
286
287 Examples:
288
289 >>> qw('1 2')
290 ['1', '2']
291
292 >>> qw(['a b','1 2',['m n','p q']])
293 [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]]
294
295 >>> qw(['a b','1 2',['m n','p q']],flat=1)
296 ['a', 'b', '1', '2', 'm', 'n', 'p', 'q']
297 """
298
299 if isinstance(words, basestring):
300 return [word.strip() for word in words.split(sep,maxsplit)
301 if word and not word.isspace() ]
302 if flat:
303 return flatten(map(qw,words,[1]*len(words)))
304 return map(qw,words)
305
306
307 def qwflat(words,sep=None,maxsplit=-1):
308 """Calls qw(words) in flat mode. It's just a convenient shorthand."""
309 return qw(words,1,sep,maxsplit)
310
311
312 def qw_lol(indata):
313 """qw_lol('a b') -> [['a','b']],
314 otherwise it's just a call to qw().
315
316 We need this to make sure the modules_some keys *always* end up as a
317 list of lists."""
318
319 if isinstance(indata, basestring):
320 return [qw(indata)]
321 else:
322 return qw(indata)
323
324
325 def grep(pat,list,case=1):
326 """Simple minded grep-like function.
327 grep(pat,list) returns occurrences of pat in list, None on failure.
328
329 It only does simple string matching, with no support for regexps. Use the
330 option case=0 for case-insensitive matching."""
331
332 # This is pretty crude. At least it should implement copying only references
333 # to the original data in case it's big. Now it copies the data for output.
334 out=[]
335 if case:
336 for term in list:
337 if term.find(pat)>-1: out.append(term)
338 else:
339 lpat=pat.lower()
340 for term in list:
341 if term.lower().find(lpat)>-1: out.append(term)
342
343 if len(out): return out
344 else: return None
345
346
347 def dgrep(pat,*opts):
348 """Return grep() on dir()+dir(__builtins__).
349
350 A very common use of grep() when working interactively."""
351
352 return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts)
353
354
355 def idgrep(pat):
356 """Case-insensitive dgrep()"""
357
358 return dgrep(pat,0)
359
360
361 def igrep(pat,list):
362 """Synonym for case-insensitive grep."""
363
364 return grep(pat,list,case=0)
365
366
367 260 def indent(instr,nspaces=4, ntabs=0, flatten=False):
368 261 """Indent a string a given number of spaces or tabstops.
369 262
370 263 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
371 264
372 265 Parameters
373 266 ----------
374 267
375 268 instr : basestring
376 269 The string to be indented.
377 270 nspaces : int (default: 4)
378 271 The number of spaces to be indented.
379 272 ntabs : int (default: 0)
380 273 The number of tabs to be indented.
381 274 flatten : bool (default: False)
382 275 Whether to scrub existing indentation. If True, all lines will be
383 276 aligned to the same indentation. If False, existing indentation will
384 277 be strictly increased.
385 278
386 279 Returns
387 280 -------
388 281
389 282 str|unicode : string indented by ntabs and nspaces.
390 283
391 284 """
392 285 if instr is None:
393 286 return
394 287 ind = '\t'*ntabs+' '*nspaces
395 288 if flatten:
396 289 pat = re.compile(r'^\s*', re.MULTILINE)
397 290 else:
398 291 pat = re.compile(r'^', re.MULTILINE)
399 292 outstr = re.sub(pat, ind, instr)
400 293 if outstr.endswith(os.linesep+ind):
401 294 return outstr[:-len(ind)]
402 295 else:
403 296 return outstr
404 297
405 298
406 299 def list_strings(arg):
407 300 """Always return a list of strings, given a string or list of strings
408 301 as input.
409 302
410 303 :Examples:
411 304
412 305 In [7]: list_strings('A single string')
413 306 Out[7]: ['A single string']
414 307
415 308 In [8]: list_strings(['A single string in a list'])
416 309 Out[8]: ['A single string in a list']
417 310
418 311 In [9]: list_strings(['A','list','of','strings'])
419 312 Out[9]: ['A', 'list', 'of', 'strings']
420 313 """
421 314
422 315 if isinstance(arg,basestring): return [arg]
423 316 else: return arg
424 317
425 318
426 319 def marquee(txt='',width=78,mark='*'):
427 320 """Return the input string centered in a 'marquee'.
428 321
429 322 :Examples:
430 323
431 324 In [16]: marquee('A test',40)
432 325 Out[16]: '**************** A test ****************'
433 326
434 327 In [17]: marquee('A test',40,'-')
435 328 Out[17]: '---------------- A test ----------------'
436 329
437 330 In [18]: marquee('A test',40,' ')
438 331 Out[18]: ' A test '
439 332
440 333 """
441 334 if not txt:
442 335 return (mark*width)[:width]
443 336 nmark = (width-len(txt)-2)//len(mark)//2
444 337 if nmark < 0: nmark =0
445 338 marks = mark*nmark
446 339 return '%s %s %s' % (marks,txt,marks)
447 340
448 341
449 342 ini_spaces_re = re.compile(r'^(\s+)')
450 343
451 344 def num_ini_spaces(strng):
452 345 """Return the number of initial spaces in a string"""
453 346
454 347 ini_spaces = ini_spaces_re.match(strng)
455 348 if ini_spaces:
456 349 return ini_spaces.end()
457 350 else:
458 351 return 0
459 352
460 353
461 354 def format_screen(strng):
462 355 """Format a string for screen printing.
463 356
464 357 This removes some latex-type format codes."""
465 358 # Paragraph continue
466 359 par_re = re.compile(r'\\$',re.MULTILINE)
467 360 strng = par_re.sub('',strng)
468 361 return strng
469 362
470 363
471 364 def dedent(text):
472 365 """Equivalent of textwrap.dedent that ignores unindented first line.
473 366
474 367 This means it will still dedent strings like:
475 368 '''foo
476 369 is a bar
477 370 '''
478 371
479 372 For use in wrap_paragraphs.
480 373 """
481 374
482 375 if text.startswith('\n'):
483 376 # text starts with blank line, don't ignore the first line
484 377 return textwrap.dedent(text)
485 378
486 379 # split first line
487 380 splits = text.split('\n',1)
488 381 if len(splits) == 1:
489 382 # only one line
490 383 return textwrap.dedent(text)
491 384
492 385 first, rest = splits
493 386 # dedent everything but the first line
494 387 rest = textwrap.dedent(rest)
495 388 return '\n'.join([first, rest])
496 389
497 390
498 391 def wrap_paragraphs(text, ncols=80):
499 392 """Wrap multiple paragraphs to fit a specified width.
500 393
501 394 This is equivalent to textwrap.wrap, but with support for multiple
502 395 paragraphs, as separated by empty lines.
503 396
504 397 Returns
505 398 -------
506 399
507 400 list of complete paragraphs, wrapped to fill `ncols` columns.
508 401 """
509 402 paragraph_re = re.compile(r'\n(\s*\n)+', re.MULTILINE)
510 403 text = dedent(text).strip()
511 404 paragraphs = paragraph_re.split(text)[::2] # every other entry is space
512 405 out_ps = []
513 406 indent_re = re.compile(r'\n\s+', re.MULTILINE)
514 407 for p in paragraphs:
515 408 # presume indentation that survives dedent is meaningful formatting,
516 409 # so don't fill unless text is flush.
517 410 if indent_re.search(p) is None:
518 411 # wrap paragraph
519 412 p = textwrap.fill(p, ncols)
520 413 out_ps.append(p)
521 414 return out_ps
522 415
523 416
524 417 def long_substr(data):
525 418 """Return the longest common substring in a list of strings.
526 419
527 420 Credit: http://stackoverflow.com/questions/2892931/longest-common-substring-from-more-than-two-strings-python
528 421 """
529 422 substr = ''
530 423 if len(data) > 1 and len(data[0]) > 0:
531 424 for i in range(len(data[0])):
532 425 for j in range(len(data[0])-i+1):
533 426 if j > len(substr) and all(data[0][i:i+j] in x for x in data):
534 427 substr = data[0][i:i+j]
535 428 elif len(data) == 1:
536 429 substr = data[0]
537 430 return substr
538 431
539 432
540 433 def strip_email_quotes(text):
541 434 """Strip leading email quotation characters ('>').
542 435
543 436 Removes any combination of leading '>' interspersed with whitespace that
544 437 appears *identically* in all lines of the input text.
545 438
546 439 Parameters
547 440 ----------
548 441 text : str
549 442
550 443 Examples
551 444 --------
552 445
553 446 Simple uses::
554 447
555 448 In [2]: strip_email_quotes('> > text')
556 449 Out[2]: 'text'
557 450
558 451 In [3]: strip_email_quotes('> > text\\n> > more')
559 452 Out[3]: 'text\\nmore'
560 453
561 454 Note how only the common prefix that appears in all lines is stripped::
562 455
563 456 In [4]: strip_email_quotes('> > text\\n> > more\\n> more...')
564 457 Out[4]: '> text\\n> more\\nmore...'
565 458
566 459 So if any line has no quote marks ('>') , then none are stripped from any
567 460 of them ::
568 461
569 462 In [5]: strip_email_quotes('> > text\\n> > more\\nlast different')
570 463 Out[5]: '> > text\\n> > more\\nlast different'
571 464 """
572 465 lines = text.splitlines()
573 466 matches = set()
574 467 for line in lines:
575 468 prefix = re.match(r'^(\s*>[ >]*)', line)
576 469 if prefix:
577 470 matches.add(prefix.group(1))
578 471 else:
579 472 break
580 473 else:
581 474 prefix = long_substr(list(matches))
582 475 if prefix:
583 476 strip = len(prefix)
584 477 text = '\n'.join([ ln[strip:] for ln in lines])
585 478 return text
586 479
587 480
588 481 class EvalFormatter(Formatter):
589 482 """A String Formatter that allows evaluation of simple expressions.
590 483
591 484 Note that this version interprets a : as specifying a format string (as per
592 485 standard string formatting), so if slicing is required, you must explicitly
593 486 create a slice.
594 487
595 488 This is to be used in templating cases, such as the parallel batch
596 489 script templates, where simple arithmetic on arguments is useful.
597 490
598 491 Examples
599 492 --------
600 493
601 494 In [1]: f = EvalFormatter()
602 495 In [2]: f.format('{n//4}', n=8)
603 496 Out [2]: '2'
604 497
605 498 In [3]: f.format("{greeting[slice(2,4)]}", greeting="Hello")
606 499 Out [3]: 'll'
607 500 """
608 501 def get_field(self, name, args, kwargs):
609 502 v = eval(name, kwargs)
610 503 return v, name
611 504
612 505
613 506 @skip_doctest_py3
614 507 class FullEvalFormatter(Formatter):
615 508 """A String Formatter that allows evaluation of simple expressions.
616 509
617 510 Any time a format key is not found in the kwargs,
618 511 it will be tried as an expression in the kwargs namespace.
619 512
620 513 Note that this version allows slicing using [1:2], so you cannot specify
621 514 a format string. Use :class:`EvalFormatter` to permit format strings.
622 515
623 516 Examples
624 517 --------
625 518
626 519 In [1]: f = FullEvalFormatter()
627 520 In [2]: f.format('{n//4}', n=8)
628 521 Out[2]: u'2'
629 522
630 523 In [3]: f.format('{list(range(5))[2:4]}')
631 524 Out[3]: u'[2, 3]'
632 525
633 526 In [4]: f.format('{3*2}')
634 527 Out[4]: u'6'
635 528 """
636 529 # copied from Formatter._vformat with minor changes to allow eval
637 530 # and replace the format_spec code with slicing
638 531 def _vformat(self, format_string, args, kwargs, used_args, recursion_depth):
639 532 if recursion_depth < 0:
640 533 raise ValueError('Max string recursion exceeded')
641 534 result = []
642 535 for literal_text, field_name, format_spec, conversion in \
643 536 self.parse(format_string):
644 537
645 538 # output the literal text
646 539 if literal_text:
647 540 result.append(literal_text)
648 541
649 542 # if there's a field, output it
650 543 if field_name is not None:
651 544 # this is some markup, find the object and do
652 545 # the formatting
653 546
654 547 if format_spec:
655 548 # override format spec, to allow slicing:
656 549 field_name = ':'.join([field_name, format_spec])
657 550
658 551 # eval the contents of the field for the object
659 552 # to be formatted
660 553 obj = eval(field_name, kwargs)
661 554
662 555 # do any conversion on the resulting object
663 556 obj = self.convert_field(obj, conversion)
664 557
665 558 # format the object and append to the result
666 559 result.append(self.format_field(obj, ''))
667 560
668 561 return u''.join(py3compat.cast_unicode(s) for s in result)
669 562
670 563
671 564 @skip_doctest_py3
672 565 class DollarFormatter(FullEvalFormatter):
673 566 """Formatter allowing Itpl style $foo replacement, for names and attribute
674 567 access only. Standard {foo} replacement also works, and allows full
675 568 evaluation of its arguments.
676 569
677 570 Examples
678 571 --------
679 572 In [1]: f = DollarFormatter()
680 573 In [2]: f.format('{n//4}', n=8)
681 574 Out[2]: u'2'
682 575
683 576 In [3]: f.format('23 * 76 is $result', result=23*76)
684 577 Out[3]: u'23 * 76 is 1748'
685 578
686 579 In [4]: f.format('$a or {b}', a=1, b=2)
687 580 Out[4]: u'1 or 2'
688 581 """
689 582 _dollar_pattern = re.compile("(.*?)\$(\$?[\w\.]+)")
690 583 def parse(self, fmt_string):
691 584 for literal_txt, field_name, format_spec, conversion \
692 585 in Formatter.parse(self, fmt_string):
693 586
694 587 # Find $foo patterns in the literal text.
695 588 continue_from = 0
696 589 txt = ""
697 590 for m in self._dollar_pattern.finditer(literal_txt):
698 591 new_txt, new_field = m.group(1,2)
699 592 # $$foo --> $foo
700 593 if new_field.startswith("$"):
701 594 txt += new_txt + new_field
702 595 else:
703 596 yield (txt + new_txt, new_field, "", None)
704 597 txt = ""
705 598 continue_from = m.end()
706 599
707 600 # Re-yield the {foo} style pattern
708 601 yield (txt + literal_txt[continue_from:], field_name, format_spec, conversion)
709 602
710 603 #-----------------------------------------------------------------------------
711 604 # Utils to columnize a list of string
712 605 #-----------------------------------------------------------------------------
713 606
714 607 def _chunks(l, n):
715 608 """Yield successive n-sized chunks from l."""
716 609 for i in xrange(0, len(l), n):
717 610 yield l[i:i+n]
718 611
719 612
720 613 def _find_optimal(rlist , separator_size=2 , displaywidth=80):
721 614 """Calculate optimal info to columnize a list of string"""
722 615 for nrow in range(1, len(rlist)+1) :
723 616 chk = map(max,_chunks(rlist, nrow))
724 617 sumlength = sum(chk)
725 618 ncols = len(chk)
726 619 if sumlength+separator_size*(ncols-1) <= displaywidth :
727 620 break;
728 621 return {'columns_numbers' : ncols,
729 622 'optimal_separator_width':(displaywidth - sumlength)/(ncols-1) if (ncols -1) else 0,
730 623 'rows_numbers' : nrow,
731 624 'columns_width' : chk
732 625 }
733 626
734 627
735 628 def _get_or_default(mylist, i, default=None):
736 629 """return list item number, or default if don't exist"""
737 630 if i >= len(mylist):
738 631 return default
739 632 else :
740 633 return mylist[i]
741 634
742 635
743 636 @skip_doctest
744 637 def compute_item_matrix(items, empty=None, *args, **kwargs) :
745 638 """Returns a nested list, and info to columnize items
746 639
747 640 Parameters
748 641 ----------
749 642
750 643 items :
751 644 list of strings to columize
752 645 empty : (default None)
753 646 default value to fill list if needed
754 647 separator_size : int (default=2)
755 648 How much caracters will be used as a separation between each columns.
756 649 displaywidth : int (default=80)
757 650 The width of the area onto wich the columns should enter
758 651
759 652 Returns
760 653 -------
761 654
762 655 Returns a tuple of (strings_matrix, dict_info)
763 656
764 657 strings_matrix :
765 658
766 659 nested list of string, the outer most list contains as many list as
767 660 rows, the innermost lists have each as many element as colums. If the
768 661 total number of elements in `items` does not equal the product of
769 662 rows*columns, the last element of some lists are filled with `None`.
770 663
771 664 dict_info :
772 665 some info to make columnize easier:
773 666
774 667 columns_numbers : number of columns
775 668 rows_numbers : number of rows
776 669 columns_width : list of with of each columns
777 670 optimal_separator_width : best separator width between columns
778 671
779 672 Examples
780 673 --------
781 674
782 675 In [1]: l = ['aaa','b','cc','d','eeeee','f','g','h','i','j','k','l']
783 676 ...: compute_item_matrix(l,displaywidth=12)
784 677 Out[1]:
785 678 ([['aaa', 'f', 'k'],
786 679 ['b', 'g', 'l'],
787 680 ['cc', 'h', None],
788 681 ['d', 'i', None],
789 682 ['eeeee', 'j', None]],
790 683 {'columns_numbers': 3,
791 684 'columns_width': [5, 1, 1],
792 685 'optimal_separator_width': 2,
793 686 'rows_numbers': 5})
794 687
795 688 """
796 689 info = _find_optimal(map(len, items), *args, **kwargs)
797 690 nrow, ncol = info['rows_numbers'], info['columns_numbers']
798 691 return ([[ _get_or_default(items, c*nrow+i, default=empty) for c in range(ncol) ] for i in range(nrow) ], info)
799 692
800 693
801 694 def columnize(items, separator=' ', displaywidth=80):
802 695 """ Transform a list of strings into a single string with columns.
803 696
804 697 Parameters
805 698 ----------
806 699 items : sequence of strings
807 700 The strings to process.
808 701
809 702 separator : str, optional [default is two spaces]
810 703 The string that separates columns.
811 704
812 705 displaywidth : int, optional [default is 80]
813 706 Width of the display in number of characters.
814 707
815 708 Returns
816 709 -------
817 710 The formatted string.
818 711 """
819 712 if not items :
820 713 return '\n'
821 714 matrix, info = compute_item_matrix(items, separator_size=len(separator), displaywidth=displaywidth)
822 715 fmatrix = [filter(None, x) for x in matrix]
823 716 sjoin = lambda x : separator.join([ y.ljust(w, ' ') for y, w in zip(x, info['columns_width'])])
824 717 return '\n'.join(map(sjoin, fmatrix))+'\n'
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now