##// END OF EJS Templates
Consolidate utils.pyfile into utils.openpy
Thomas Kluyver -
Show More
@@ -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,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 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now