##// END OF EJS Templates
Use term width to determine header length
Vincent Woo -
Show More
@@ -1,1483 +1,1485 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 Verbose and colourful traceback formatting.
4 4
5 5 **ColorTB**
6 6
7 7 I've always found it a bit hard to visually parse tracebacks in Python. The
8 8 ColorTB class is a solution to that problem. It colors the different parts of a
9 9 traceback in a manner similar to what you would expect from a syntax-highlighting
10 10 text editor.
11 11
12 12 Installation instructions for ColorTB::
13 13
14 14 import sys,ultratb
15 15 sys.excepthook = ultratb.ColorTB()
16 16
17 17 **VerboseTB**
18 18
19 19 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
20 20 of useful info when a traceback occurs. Ping originally had it spit out HTML
21 21 and intended it for CGI programmers, but why should they have all the fun? I
22 22 altered it to spit out colored text to the terminal. It's a bit overwhelming,
23 23 but kind of neat, and maybe useful for long-running programs that you believe
24 24 are bug-free. If a crash *does* occur in that type of program you want details.
25 25 Give it a shot--you'll love it or you'll hate it.
26 26
27 27 .. note::
28 28
29 29 The Verbose mode prints the variables currently visible where the exception
30 30 happened (shortening their strings if too long). This can potentially be
31 31 very slow, if you happen to have a huge data structure whose string
32 32 representation is complex to compute. Your computer may appear to freeze for
33 33 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
34 34 with Ctrl-C (maybe hitting it more than once).
35 35
36 36 If you encounter this kind of situation often, you may want to use the
37 37 Verbose_novars mode instead of the regular Verbose, which avoids formatting
38 38 variables (but otherwise includes the information and context given by
39 39 Verbose).
40 40
41 41 .. note::
42 42
43 43 The verbose mode print all variables in the stack, which means it can
44 44 potentially leak sensitive information like access keys, or unencryted
45 45 password.
46 46
47 47 Installation instructions for VerboseTB::
48 48
49 49 import sys,ultratb
50 50 sys.excepthook = ultratb.VerboseTB()
51 51
52 52 Note: Much of the code in this module was lifted verbatim from the standard
53 53 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
54 54
55 55 Color schemes
56 56 -------------
57 57
58 58 The colors are defined in the class TBTools through the use of the
59 59 ColorSchemeTable class. Currently the following exist:
60 60
61 61 - NoColor: allows all of this module to be used in any terminal (the color
62 62 escapes are just dummy blank strings).
63 63
64 64 - Linux: is meant to look good in a terminal like the Linux console (black
65 65 or very dark background).
66 66
67 67 - LightBG: similar to Linux but swaps dark/light colors to be more readable
68 68 in light background terminals.
69 69
70 70 You can implement other color schemes easily, the syntax is fairly
71 71 self-explanatory. Please send back new schemes you develop to the author for
72 72 possible inclusion in future releases.
73 73
74 74 Inheritance diagram:
75 75
76 76 .. inheritance-diagram:: IPython.core.ultratb
77 77 :parts: 3
78 78 """
79 79
80 80 #*****************************************************************************
81 81 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
82 82 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
83 83 #
84 84 # Distributed under the terms of the BSD License. The full license is in
85 85 # the file COPYING, distributed as part of this software.
86 86 #*****************************************************************************
87 87
88 88 from __future__ import absolute_import
89 89 from __future__ import unicode_literals
90 90 from __future__ import print_function
91 91
92 92 import dis
93 93 import inspect
94 94 import keyword
95 95 import linecache
96 96 import os
97 97 import pydoc
98 98 import re
99 99 import sys
100 100 import time
101 101 import tokenize
102 102 import traceback
103 103 import types
104 104
105 105 try: # Python 2
106 106 generate_tokens = tokenize.generate_tokens
107 107 except AttributeError: # Python 3
108 108 generate_tokens = tokenize.tokenize
109 109
110 110 # For purposes of monkeypatching inspect to fix a bug in it.
111 111 from inspect import getsourcefile, getfile, getmodule, \
112 112 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
113 113
114 114 # IPython's own modules
115 115 # Modified pdb which doesn't damage IPython's readline handling
116 116 from IPython import get_ipython
117 117 from IPython.core import debugger
118 118 from IPython.core.display_trap import DisplayTrap
119 119 from IPython.core.excolors import exception_colors
120 120 from IPython.utils import PyColorize
121 121 from IPython.utils import io
122 122 from IPython.utils import openpy
123 123 from IPython.utils import path as util_path
124 124 from IPython.utils import py3compat
125 125 from IPython.utils import ulinecache
126 126 from IPython.utils.data import uniq_stable
127 from IPython.utils.terminal import get_terminal_size
127 128 from logging import info, error
128 129
129 130 import IPython.utils.colorable as colorable
130 131
131 132 # Globals
132 133 # amount of space to put line numbers before verbose tracebacks
133 134 INDENT_SIZE = 8
134 135
135 136 # Default color scheme. This is used, for example, by the traceback
136 137 # formatter. When running in an actual IPython instance, the user's rc.colors
137 138 # value is used, but having a module global makes this functionality available
138 139 # to users of ultratb who are NOT running inside ipython.
139 140 DEFAULT_SCHEME = 'NoColor'
140 141
141 142 # ---------------------------------------------------------------------------
142 143 # Code begins
143 144
144 145 # Utility functions
145 146 def inspect_error():
146 147 """Print a message about internal inspect errors.
147 148
148 149 These are unfortunately quite common."""
149 150
150 151 error('Internal Python error in the inspect module.\n'
151 152 'Below is the traceback from this internal error.\n')
152 153
153 154
154 155 # This function is a monkeypatch we apply to the Python inspect module. We have
155 156 # now found when it's needed (see discussion on issue gh-1456), and we have a
156 157 # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if
157 158 # the monkeypatch is not applied. TK, Aug 2012.
158 159 def findsource(object):
159 160 """Return the entire source file and starting line number for an object.
160 161
161 162 The argument may be a module, class, method, function, traceback, frame,
162 163 or code object. The source code is returned as a list of all the lines
163 164 in the file and the line number indexes a line in that list. An IOError
164 165 is raised if the source code cannot be retrieved.
165 166
166 167 FIXED version with which we monkeypatch the stdlib to work around a bug."""
167 168
168 169 file = getsourcefile(object) or getfile(object)
169 170 # If the object is a frame, then trying to get the globals dict from its
170 171 # module won't work. Instead, the frame object itself has the globals
171 172 # dictionary.
172 173 globals_dict = None
173 174 if inspect.isframe(object):
174 175 # XXX: can this ever be false?
175 176 globals_dict = object.f_globals
176 177 else:
177 178 module = getmodule(object, file)
178 179 if module:
179 180 globals_dict = module.__dict__
180 181 lines = linecache.getlines(file, globals_dict)
181 182 if not lines:
182 183 raise IOError('could not get source code')
183 184
184 185 if ismodule(object):
185 186 return lines, 0
186 187
187 188 if isclass(object):
188 189 name = object.__name__
189 190 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
190 191 # make some effort to find the best matching class definition:
191 192 # use the one with the least indentation, which is the one
192 193 # that's most probably not inside a function definition.
193 194 candidates = []
194 195 for i in range(len(lines)):
195 196 match = pat.match(lines[i])
196 197 if match:
197 198 # if it's at toplevel, it's already the best one
198 199 if lines[i][0] == 'c':
199 200 return lines, i
200 201 # else add whitespace to candidate list
201 202 candidates.append((match.group(1), i))
202 203 if candidates:
203 204 # this will sort by whitespace, and by line number,
204 205 # less whitespace first
205 206 candidates.sort()
206 207 return lines, candidates[0][1]
207 208 else:
208 209 raise IOError('could not find class definition')
209 210
210 211 if ismethod(object):
211 212 object = object.__func__
212 213 if isfunction(object):
213 214 object = object.__code__
214 215 if istraceback(object):
215 216 object = object.tb_frame
216 217 if isframe(object):
217 218 object = object.f_code
218 219 if iscode(object):
219 220 if not hasattr(object, 'co_firstlineno'):
220 221 raise IOError('could not find function definition')
221 222 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
222 223 pmatch = pat.match
223 224 # fperez - fix: sometimes, co_firstlineno can give a number larger than
224 225 # the length of lines, which causes an error. Safeguard against that.
225 226 lnum = min(object.co_firstlineno, len(lines)) - 1
226 227 while lnum > 0:
227 228 if pmatch(lines[lnum]):
228 229 break
229 230 lnum -= 1
230 231
231 232 return lines, lnum
232 233 raise IOError('could not find code object')
233 234
234 235
235 236 # This is a patched version of inspect.getargs that applies the (unmerged)
236 237 # patch for http://bugs.python.org/issue14611 by Stefano Taschini. This fixes
237 238 # https://github.com/ipython/ipython/issues/8205 and
238 239 # https://github.com/ipython/ipython/issues/8293
239 240 def getargs(co):
240 241 """Get information about the arguments accepted by a code object.
241 242
242 243 Three things are returned: (args, varargs, varkw), where 'args' is
243 244 a list of argument names (possibly containing nested lists), and
244 245 'varargs' and 'varkw' are the names of the * and ** arguments or None."""
245 246 if not iscode(co):
246 247 raise TypeError('{!r} is not a code object'.format(co))
247 248
248 249 nargs = co.co_argcount
249 250 names = co.co_varnames
250 251 args = list(names[:nargs])
251 252 step = 0
252 253
253 254 # The following acrobatics are for anonymous (tuple) arguments.
254 255 for i in range(nargs):
255 256 if args[i][:1] in ('', '.'):
256 257 stack, remain, count = [], [], []
257 258 while step < len(co.co_code):
258 259 op = ord(co.co_code[step])
259 260 step = step + 1
260 261 if op >= dis.HAVE_ARGUMENT:
261 262 opname = dis.opname[op]
262 263 value = ord(co.co_code[step]) + ord(co.co_code[step+1])*256
263 264 step = step + 2
264 265 if opname in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'):
265 266 remain.append(value)
266 267 count.append(value)
267 268 elif opname in ('STORE_FAST', 'STORE_DEREF'):
268 269 if op in dis.haslocal:
269 270 stack.append(co.co_varnames[value])
270 271 elif op in dis.hasfree:
271 272 stack.append((co.co_cellvars + co.co_freevars)[value])
272 273 # Special case for sublists of length 1: def foo((bar))
273 274 # doesn't generate the UNPACK_TUPLE bytecode, so if
274 275 # `remain` is empty here, we have such a sublist.
275 276 if not remain:
276 277 stack[0] = [stack[0]]
277 278 break
278 279 else:
279 280 remain[-1] = remain[-1] - 1
280 281 while remain[-1] == 0:
281 282 remain.pop()
282 283 size = count.pop()
283 284 stack[-size:] = [stack[-size:]]
284 285 if not remain:
285 286 break
286 287 remain[-1] = remain[-1] - 1
287 288 if not remain:
288 289 break
289 290 args[i] = stack[0]
290 291
291 292 varargs = None
292 293 if co.co_flags & inspect.CO_VARARGS:
293 294 varargs = co.co_varnames[nargs]
294 295 nargs = nargs + 1
295 296 varkw = None
296 297 if co.co_flags & inspect.CO_VARKEYWORDS:
297 298 varkw = co.co_varnames[nargs]
298 299 return inspect.Arguments(args, varargs, varkw)
299 300
300 301
301 302 # Monkeypatch inspect to apply our bugfix.
302 303 def with_patch_inspect(f):
303 304 """decorator for monkeypatching inspect.findsource"""
304 305
305 306 def wrapped(*args, **kwargs):
306 307 save_findsource = inspect.findsource
307 308 save_getargs = inspect.getargs
308 309 inspect.findsource = findsource
309 310 inspect.getargs = getargs
310 311 try:
311 312 return f(*args, **kwargs)
312 313 finally:
313 314 inspect.findsource = save_findsource
314 315 inspect.getargs = save_getargs
315 316
316 317 return wrapped
317 318
318 319
319 320 if py3compat.PY3:
320 321 fixed_getargvalues = inspect.getargvalues
321 322 else:
322 323 # Fixes for https://github.com/ipython/ipython/issues/8293
323 324 # and https://github.com/ipython/ipython/issues/8205.
324 325 # The relevant bug is caused by failure to correctly handle anonymous tuple
325 326 # unpacking, which only exists in Python 2.
326 327 fixed_getargvalues = with_patch_inspect(inspect.getargvalues)
327 328
328 329
329 330 def fix_frame_records_filenames(records):
330 331 """Try to fix the filenames in each record from inspect.getinnerframes().
331 332
332 333 Particularly, modules loaded from within zip files have useless filenames
333 334 attached to their code object, and inspect.getinnerframes() just uses it.
334 335 """
335 336 fixed_records = []
336 337 for frame, filename, line_no, func_name, lines, index in records:
337 338 # Look inside the frame's globals dictionary for __file__,
338 339 # which should be better. However, keep Cython filenames since
339 340 # we prefer the source filenames over the compiled .so file.
340 341 filename = py3compat.cast_unicode_py2(filename, "utf-8")
341 342 if not filename.endswith(('.pyx', '.pxd', '.pxi')):
342 343 better_fn = frame.f_globals.get('__file__', None)
343 344 if isinstance(better_fn, str):
344 345 # Check the type just in case someone did something weird with
345 346 # __file__. It might also be None if the error occurred during
346 347 # import.
347 348 filename = better_fn
348 349 fixed_records.append((frame, filename, line_no, func_name, lines, index))
349 350 return fixed_records
350 351
351 352
352 353 @with_patch_inspect
353 354 def _fixed_getinnerframes(etb, context=1, tb_offset=0):
354 355 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
355 356
356 357 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
357 358 # If the error is at the console, don't build any context, since it would
358 359 # otherwise produce 5 blank lines printed out (there is no file at the
359 360 # console)
360 361 rec_check = records[tb_offset:]
361 362 try:
362 363 rname = rec_check[0][1]
363 364 if rname == '<ipython console>' or rname.endswith('<string>'):
364 365 return rec_check
365 366 except IndexError:
366 367 pass
367 368
368 369 aux = traceback.extract_tb(etb)
369 370 assert len(records) == len(aux)
370 371 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
371 372 maybeStart = lnum - 1 - context // 2
372 373 start = max(maybeStart, 0)
373 374 end = start + context
374 375 lines = ulinecache.getlines(file)[start:end]
375 376 buf = list(records[i])
376 377 buf[LNUM_POS] = lnum
377 378 buf[INDEX_POS] = lnum - 1 - start
378 379 buf[LINES_POS] = lines
379 380 records[i] = tuple(buf)
380 381 return records[tb_offset:]
381 382
382 383 # Helper function -- largely belongs to VerboseTB, but we need the same
383 384 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
384 385 # can be recognized properly by ipython.el's py-traceback-line-re
385 386 # (SyntaxErrors have to be treated specially because they have no traceback)
386 387
387 388 _parser = PyColorize.Parser()
388 389
389 390
390 391 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None, scheme=None):
391 392 numbers_width = INDENT_SIZE - 1
392 393 res = []
393 394 i = lnum - index
394 395
395 396 # This lets us get fully syntax-highlighted tracebacks.
396 397 if scheme is None:
397 398 ipinst = get_ipython()
398 399 if ipinst is not None:
399 400 scheme = ipinst.colors
400 401 else:
401 402 scheme = DEFAULT_SCHEME
402 403
403 404 _line_format = _parser.format2
404 405
405 406 for line in lines:
406 407 line = py3compat.cast_unicode(line)
407 408
408 409 new_line, err = _line_format(line, 'str', scheme)
409 410 if not err: line = new_line
410 411
411 412 if i == lnum:
412 413 # This is the line with the error
413 414 pad = numbers_width - len(str(i))
414 415 num = '%s%s' % (debugger.make_arrow(pad), str(lnum))
415 416 line = '%s%s%s %s%s' % (Colors.linenoEm, num,
416 417 Colors.line, line, Colors.Normal)
417 418 else:
418 419 num = '%*s' % (numbers_width, i)
419 420 line = '%s%s%s %s' % (Colors.lineno, num,
420 421 Colors.Normal, line)
421 422
422 423 res.append(line)
423 424 if lvals and i == lnum:
424 425 res.append(lvals + '\n')
425 426 i = i + 1
426 427 return res
427 428
428 429 def is_recursion_error(etype, value, records):
429 430 try:
430 431 # RecursionError is new in Python 3.5
431 432 recursion_error_type = RecursionError
432 433 except NameError:
433 434 recursion_error_type = RuntimeError
434 435
435 436 # The default recursion limit is 1000, but some of that will be taken up
436 437 # by stack frames in IPython itself. >500 frames probably indicates
437 438 # a recursion error.
438 439 return (etype is recursion_error_type) \
439 440 and "recursion" in str(value).lower() \
440 441 and len(records) > 500
441 442
442 443 def find_recursion(etype, value, records):
443 444 """Identify the repeating stack frames from a RecursionError traceback
444 445
445 446 'records' is a list as returned by VerboseTB.get_records()
446 447
447 448 Returns (last_unique, repeat_length)
448 449 """
449 450 # This involves a bit of guesswork - we want to show enough of the traceback
450 451 # to indicate where the recursion is occurring. We guess that the innermost
451 452 # quarter of the traceback (250 frames by default) is repeats, and find the
452 453 # first frame (from in to out) that looks different.
453 454 if not is_recursion_error(etype, value, records):
454 455 return len(records), 0
455 456
456 457 # Select filename, lineno, func_name to track frames with
457 458 records = [r[1:4] for r in records]
458 459 inner_frames = records[-(len(records)//4):]
459 460 frames_repeated = set(inner_frames)
460 461
461 462 last_seen_at = {}
462 463 longest_repeat = 0
463 464 i = len(records)
464 465 for frame in reversed(records):
465 466 i -= 1
466 467 if frame not in frames_repeated:
467 468 last_unique = i
468 469 break
469 470
470 471 if frame in last_seen_at:
471 472 distance = last_seen_at[frame] - i
472 473 longest_repeat = max(longest_repeat, distance)
473 474
474 475 last_seen_at[frame] = i
475 476 else:
476 477 last_unique = 0 # The whole traceback was recursion
477 478
478 479 return last_unique, longest_repeat
479 480
480 481 #---------------------------------------------------------------------------
481 482 # Module classes
482 483 class TBTools(colorable.Colorable):
483 484 """Basic tools used by all traceback printer classes."""
484 485
485 486 # Number of frames to skip when reporting tracebacks
486 487 tb_offset = 0
487 488
488 489 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
489 490 # Whether to call the interactive pdb debugger after printing
490 491 # tracebacks or not
491 492 super(TBTools, self).__init__(parent=parent, config=config)
492 493 self.call_pdb = call_pdb
493 494
494 495 # Output stream to write to. Note that we store the original value in
495 496 # a private attribute and then make the public ostream a property, so
496 497 # that we can delay accessing io.stdout until runtime. The way
497 498 # things are written now, the io.stdout object is dynamically managed
498 499 # so a reference to it should NEVER be stored statically. This
499 500 # property approach confines this detail to a single location, and all
500 501 # subclasses can simply access self.ostream for writing.
501 502 self._ostream = ostream
502 503
503 504 # Create color table
504 505 self.color_scheme_table = exception_colors()
505 506
506 507 self.set_colors(color_scheme)
507 508 self.old_scheme = color_scheme # save initial value for toggles
508 509
509 510 if call_pdb:
510 511 self.pdb = debugger.Pdb(self.color_scheme_table.active_scheme_name)
511 512 else:
512 513 self.pdb = None
513 514
514 515 def _get_ostream(self):
515 516 """Output stream that exceptions are written to.
516 517
517 518 Valid values are:
518 519
519 520 - None: the default, which means that IPython will dynamically resolve
520 521 to io.stdout. This ensures compatibility with most tools, including
521 522 Windows (where plain stdout doesn't recognize ANSI escapes).
522 523
523 524 - Any object with 'write' and 'flush' attributes.
524 525 """
525 526 return io.stdout if self._ostream is None else self._ostream
526 527
527 528 def _set_ostream(self, val):
528 529 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
529 530 self._ostream = val
530 531
531 532 ostream = property(_get_ostream, _set_ostream)
532 533
533 534 def set_colors(self, *args, **kw):
534 535 """Shorthand access to the color table scheme selector method."""
535 536
536 537 # Set own color table
537 538 self.color_scheme_table.set_active_scheme(*args, **kw)
538 539 # for convenience, set Colors to the active scheme
539 540 self.Colors = self.color_scheme_table.active_colors
540 541 # Also set colors of debugger
541 542 if hasattr(self, 'pdb') and self.pdb is not None:
542 543 self.pdb.set_colors(*args, **kw)
543 544
544 545 def color_toggle(self):
545 546 """Toggle between the currently active color scheme and NoColor."""
546 547
547 548 if self.color_scheme_table.active_scheme_name == 'NoColor':
548 549 self.color_scheme_table.set_active_scheme(self.old_scheme)
549 550 self.Colors = self.color_scheme_table.active_colors
550 551 else:
551 552 self.old_scheme = self.color_scheme_table.active_scheme_name
552 553 self.color_scheme_table.set_active_scheme('NoColor')
553 554 self.Colors = self.color_scheme_table.active_colors
554 555
555 556 def stb2text(self, stb):
556 557 """Convert a structured traceback (a list) to a string."""
557 558 return '\n'.join(stb)
558 559
559 560 def text(self, etype, value, tb, tb_offset=None, context=5):
560 561 """Return formatted traceback.
561 562
562 563 Subclasses may override this if they add extra arguments.
563 564 """
564 565 tb_list = self.structured_traceback(etype, value, tb,
565 566 tb_offset, context)
566 567 return self.stb2text(tb_list)
567 568
568 569 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
569 570 context=5, mode=None):
570 571 """Return a list of traceback frames.
571 572
572 573 Must be implemented by each class.
573 574 """
574 575 raise NotImplementedError()
575 576
576 577
577 578 #---------------------------------------------------------------------------
578 579 class ListTB(TBTools):
579 580 """Print traceback information from a traceback list, with optional color.
580 581
581 582 Calling requires 3 arguments: (etype, evalue, elist)
582 583 as would be obtained by::
583 584
584 585 etype, evalue, tb = sys.exc_info()
585 586 if tb:
586 587 elist = traceback.extract_tb(tb)
587 588 else:
588 589 elist = None
589 590
590 591 It can thus be used by programs which need to process the traceback before
591 592 printing (such as console replacements based on the code module from the
592 593 standard library).
593 594
594 595 Because they are meant to be called without a full traceback (only a
595 596 list), instances of this class can't call the interactive pdb debugger."""
596 597
597 598 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None):
598 599 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
599 600 ostream=ostream, parent=parent)
600 601
601 602 def __call__(self, etype, value, elist):
602 603 self.ostream.flush()
603 604 self.ostream.write(self.text(etype, value, elist))
604 605 self.ostream.write('\n')
605 606
606 607 def structured_traceback(self, etype, value, elist, tb_offset=None,
607 608 context=5):
608 609 """Return a color formatted string with the traceback info.
609 610
610 611 Parameters
611 612 ----------
612 613 etype : exception type
613 614 Type of the exception raised.
614 615
615 616 value : object
616 617 Data stored in the exception
617 618
618 619 elist : list
619 620 List of frames, see class docstring for details.
620 621
621 622 tb_offset : int, optional
622 623 Number of frames in the traceback to skip. If not given, the
623 624 instance value is used (set in constructor).
624 625
625 626 context : int, optional
626 627 Number of lines of context information to print.
627 628
628 629 Returns
629 630 -------
630 631 String with formatted exception.
631 632 """
632 633 tb_offset = self.tb_offset if tb_offset is None else tb_offset
633 634 Colors = self.Colors
634 635 out_list = []
635 636 if elist:
636 637
637 638 if tb_offset and len(elist) > tb_offset:
638 639 elist = elist[tb_offset:]
639 640
640 641 out_list.append('Traceback %s(most recent call last)%s:' %
641 642 (Colors.normalEm, Colors.Normal) + '\n')
642 643 out_list.extend(self._format_list(elist))
643 644 # The exception info should be a single entry in the list.
644 645 lines = ''.join(self._format_exception_only(etype, value))
645 646 out_list.append(lines)
646 647
647 648 # Note: this code originally read:
648 649
649 650 ## for line in lines[:-1]:
650 651 ## out_list.append(" "+line)
651 652 ## out_list.append(lines[-1])
652 653
653 654 # This means it was indenting everything but the last line by a little
654 655 # bit. I've disabled this for now, but if we see ugliness somewhere we
655 656 # can restore it.
656 657
657 658 return out_list
658 659
659 660 def _format_list(self, extracted_list):
660 661 """Format a list of traceback entry tuples for printing.
661 662
662 663 Given a list of tuples as returned by extract_tb() or
663 664 extract_stack(), return a list of strings ready for printing.
664 665 Each string in the resulting list corresponds to the item with the
665 666 same index in the argument list. Each string ends in a newline;
666 667 the strings may contain internal newlines as well, for those items
667 668 whose source text line is not None.
668 669
669 670 Lifted almost verbatim from traceback.py
670 671 """
671 672
672 673 Colors = self.Colors
673 674 list = []
674 675 for filename, lineno, name, line in extracted_list[:-1]:
675 676 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
676 677 (Colors.filename, py3compat.cast_unicode_py2(filename, "utf-8"), Colors.Normal,
677 678 Colors.lineno, lineno, Colors.Normal,
678 679 Colors.name, py3compat.cast_unicode_py2(name, "utf-8"), Colors.Normal)
679 680 if line:
680 681 item += ' %s\n' % line.strip()
681 682 list.append(item)
682 683 # Emphasize the last entry
683 684 filename, lineno, name, line = extracted_list[-1]
684 685 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
685 686 (Colors.normalEm,
686 687 Colors.filenameEm, py3compat.cast_unicode_py2(filename, "utf-8"), Colors.normalEm,
687 688 Colors.linenoEm, lineno, Colors.normalEm,
688 689 Colors.nameEm, py3compat.cast_unicode_py2(name, "utf-8"), Colors.normalEm,
689 690 Colors.Normal)
690 691 if line:
691 692 item += '%s %s%s\n' % (Colors.line, line.strip(),
692 693 Colors.Normal)
693 694 list.append(item)
694 695 return list
695 696
696 697 def _format_exception_only(self, etype, value):
697 698 """Format the exception part of a traceback.
698 699
699 700 The arguments are the exception type and value such as given by
700 701 sys.exc_info()[:2]. The return value is a list of strings, each ending
701 702 in a newline. Normally, the list contains a single string; however,
702 703 for SyntaxError exceptions, it contains several lines that (when
703 704 printed) display detailed information about where the syntax error
704 705 occurred. The message indicating which exception occurred is the
705 706 always last string in the list.
706 707
707 708 Also lifted nearly verbatim from traceback.py
708 709 """
709 710 have_filedata = False
710 711 Colors = self.Colors
711 712 list = []
712 713 stype = Colors.excName + etype.__name__ + Colors.Normal
713 714 if value is None:
714 715 # Not sure if this can still happen in Python 2.6 and above
715 716 list.append(py3compat.cast_unicode(stype) + '\n')
716 717 else:
717 718 if issubclass(etype, SyntaxError):
718 719 have_filedata = True
719 720 if not value.filename: value.filename = "<string>"
720 721 if value.lineno:
721 722 lineno = value.lineno
722 723 textline = ulinecache.getline(value.filename, value.lineno)
723 724 else:
724 725 lineno = 'unknown'
725 726 textline = ''
726 727 list.append('%s File %s"%s"%s, line %s%s%s\n' % \
727 728 (Colors.normalEm,
728 729 Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm,
729 730 Colors.linenoEm, lineno, Colors.Normal ))
730 731 if textline == '':
731 732 textline = py3compat.cast_unicode(value.text, "utf-8")
732 733
733 734 if textline is not None:
734 735 i = 0
735 736 while i < len(textline) and textline[i].isspace():
736 737 i += 1
737 738 list.append('%s %s%s\n' % (Colors.line,
738 739 textline.strip(),
739 740 Colors.Normal))
740 741 if value.offset is not None:
741 742 s = ' '
742 743 for c in textline[i:value.offset - 1]:
743 744 if c.isspace():
744 745 s += c
745 746 else:
746 747 s += ' '
747 748 list.append('%s%s^%s\n' % (Colors.caret, s,
748 749 Colors.Normal))
749 750
750 751 try:
751 752 s = value.msg
752 753 except Exception:
753 754 s = self._some_str(value)
754 755 if s:
755 756 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
756 757 Colors.Normal, s))
757 758 else:
758 759 list.append('%s\n' % str(stype))
759 760
760 761 # sync with user hooks
761 762 if have_filedata:
762 763 ipinst = get_ipython()
763 764 if ipinst is not None:
764 765 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
765 766
766 767 return list
767 768
768 769 def get_exception_only(self, etype, value):
769 770 """Only print the exception type and message, without a traceback.
770 771
771 772 Parameters
772 773 ----------
773 774 etype : exception type
774 775 value : exception value
775 776 """
776 777 return ListTB.structured_traceback(self, etype, value, [])
777 778
778 779 def show_exception_only(self, etype, evalue):
779 780 """Only print the exception type and message, without a traceback.
780 781
781 782 Parameters
782 783 ----------
783 784 etype : exception type
784 785 value : exception value
785 786 """
786 787 # This method needs to use __call__ from *this* class, not the one from
787 788 # a subclass whose signature or behavior may be different
788 789 ostream = self.ostream
789 790 ostream.flush()
790 791 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
791 792 ostream.flush()
792 793
793 794 def _some_str(self, value):
794 795 # Lifted from traceback.py
795 796 try:
796 797 return str(value)
797 798 except:
798 799 return '<unprintable %s object>' % type(value).__name__
799 800
800 801
801 802 #----------------------------------------------------------------------------
802 803 class VerboseTB(TBTools):
803 804 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
804 805 of HTML. Requires inspect and pydoc. Crazy, man.
805 806
806 807 Modified version which optionally strips the topmost entries from the
807 808 traceback, to be used with alternate interpreters (because their own code
808 809 would appear in the traceback)."""
809 810
810 811 def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None,
811 812 tb_offset=0, long_header=False, include_vars=True,
812 813 check_cache=None):
813 814 """Specify traceback offset, headers and color scheme.
814 815
815 816 Define how many frames to drop from the tracebacks. Calling it with
816 817 tb_offset=1 allows use of this handler in interpreters which will have
817 818 their own code at the top of the traceback (VerboseTB will first
818 819 remove that frame before printing the traceback info)."""
819 820 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
820 821 ostream=ostream)
821 822 self.tb_offset = tb_offset
822 823 self.long_header = long_header
823 824 self.include_vars = include_vars
824 825 # By default we use linecache.checkcache, but the user can provide a
825 826 # different check_cache implementation. This is used by the IPython
826 827 # kernel to provide tracebacks for interactive code that is cached,
827 828 # by a compiler instance that flushes the linecache but preserves its
828 829 # own code cache.
829 830 if check_cache is None:
830 831 check_cache = linecache.checkcache
831 832 self.check_cache = check_cache
832 833
833 834 def format_records(self, records, last_unique, recursion_repeat):
834 835 """Format the stack frames of the traceback"""
835 836 frames = []
836 837 for r in records[:last_unique+recursion_repeat+1]:
837 838 #print '*** record:',file,lnum,func,lines,index # dbg
838 839 frames.append(self.format_record(*r))
839 840
840 841 if recursion_repeat:
841 842 frames.append('... last %d frames repeated, from the frame below ...\n' % recursion_repeat)
842 843 frames.append(self.format_record(*records[last_unique+recursion_repeat+1]))
843 844
844 845 return frames
845 846
846 847 def format_record(self, frame, file, lnum, func, lines, index):
847 848 """Format a single stack frame"""
848 849 Colors = self.Colors # just a shorthand + quicker name lookup
849 850 ColorsNormal = Colors.Normal # used a lot
850 851 col_scheme = self.color_scheme_table.active_scheme_name
851 852 indent = ' ' * INDENT_SIZE
852 853 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
853 854 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
854 855 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
855 856 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
856 857 ColorsNormal)
857 858 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
858 859 (Colors.vName, Colors.valEm, ColorsNormal)
859 860 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
860 861 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
861 862 Colors.vName, ColorsNormal)
862 863 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
863 864
864 865 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
865 866 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm, Colors.line,
866 867 ColorsNormal)
867 868
868 869 abspath = os.path.abspath
869 870
870 871
871 872 if not file:
872 873 file = '?'
873 874 elif file.startswith(str("<")) and file.endswith(str(">")):
874 875 # Not a real filename, no problem...
875 876 pass
876 877 elif not os.path.isabs(file):
877 878 # Try to make the filename absolute by trying all
878 879 # sys.path entries (which is also what linecache does)
879 880 for dirname in sys.path:
880 881 try:
881 882 fullname = os.path.join(dirname, file)
882 883 if os.path.isfile(fullname):
883 884 file = os.path.abspath(fullname)
884 885 break
885 886 except Exception:
886 887 # Just in case that sys.path contains very
887 888 # strange entries...
888 889 pass
889 890
890 891 file = py3compat.cast_unicode(file, util_path.fs_encoding)
891 892 link = tpl_link % file
892 893 args, varargs, varkw, locals = fixed_getargvalues(frame)
893 894
894 895 if func == '?':
895 896 call = ''
896 897 else:
897 898 # Decide whether to include variable details or not
898 899 var_repr = self.include_vars and eqrepr or nullrepr
899 900 try:
900 901 call = tpl_call % (func, inspect.formatargvalues(args,
901 902 varargs, varkw,
902 903 locals, formatvalue=var_repr))
903 904 except KeyError:
904 905 # This happens in situations like errors inside generator
905 906 # expressions, where local variables are listed in the
906 907 # line, but can't be extracted from the frame. I'm not
907 908 # 100% sure this isn't actually a bug in inspect itself,
908 909 # but since there's no info for us to compute with, the
909 910 # best we can do is report the failure and move on. Here
910 911 # we must *not* call any traceback construction again,
911 912 # because that would mess up use of %debug later on. So we
912 913 # simply report the failure and move on. The only
913 914 # limitation will be that this frame won't have locals
914 915 # listed in the call signature. Quite subtle problem...
915 916 # I can't think of a good way to validate this in a unit
916 917 # test, but running a script consisting of:
917 918 # dict( (k,v.strip()) for (k,v) in range(10) )
918 919 # will illustrate the error, if this exception catch is
919 920 # disabled.
920 921 call = tpl_call_fail % func
921 922
922 923 # Don't attempt to tokenize binary files.
923 924 if file.endswith(('.so', '.pyd', '.dll')):
924 925 return '%s %s\n' % (link, call)
925 926
926 927 elif file.endswith(('.pyc', '.pyo')):
927 928 # Look up the corresponding source file.
928 929 file = openpy.source_from_cache(file)
929 930
930 931 def linereader(file=file, lnum=[lnum], getline=ulinecache.getline):
931 932 line = getline(file, lnum[0])
932 933 lnum[0] += 1
933 934 return line
934 935
935 936 # Build the list of names on this line of code where the exception
936 937 # occurred.
937 938 try:
938 939 names = []
939 940 name_cont = False
940 941
941 942 for token_type, token, start, end, line in generate_tokens(linereader):
942 943 # build composite names
943 944 if token_type == tokenize.NAME and token not in keyword.kwlist:
944 945 if name_cont:
945 946 # Continuation of a dotted name
946 947 try:
947 948 names[-1].append(token)
948 949 except IndexError:
949 950 names.append([token])
950 951 name_cont = False
951 952 else:
952 953 # Regular new names. We append everything, the caller
953 954 # will be responsible for pruning the list later. It's
954 955 # very tricky to try to prune as we go, b/c composite
955 956 # names can fool us. The pruning at the end is easy
956 957 # to do (or the caller can print a list with repeated
957 958 # names if so desired.
958 959 names.append([token])
959 960 elif token == '.':
960 961 name_cont = True
961 962 elif token_type == tokenize.NEWLINE:
962 963 break
963 964
964 965 except (IndexError, UnicodeDecodeError, SyntaxError):
965 966 # signals exit of tokenizer
966 967 # SyntaxError can occur if the file is not actually Python
967 968 # - see gh-6300
968 969 pass
969 970 except tokenize.TokenError as msg:
970 971 _m = ("An unexpected error occurred while tokenizing input\n"
971 972 "The following traceback may be corrupted or invalid\n"
972 973 "The error message is: %s\n" % msg)
973 974 error(_m)
974 975
975 976 # Join composite names (e.g. "dict.fromkeys")
976 977 names = ['.'.join(n) for n in names]
977 978 # prune names list of duplicates, but keep the right order
978 979 unique_names = uniq_stable(names)
979 980
980 981 # Start loop over vars
981 982 lvals = []
982 983 if self.include_vars:
983 984 for name_full in unique_names:
984 985 name_base = name_full.split('.', 1)[0]
985 986 if name_base in frame.f_code.co_varnames:
986 987 if name_base in locals:
987 988 try:
988 989 value = repr(eval(name_full, locals))
989 990 except:
990 991 value = undefined
991 992 else:
992 993 value = undefined
993 994 name = tpl_local_var % name_full
994 995 else:
995 996 if name_base in frame.f_globals:
996 997 try:
997 998 value = repr(eval(name_full, frame.f_globals))
998 999 except:
999 1000 value = undefined
1000 1001 else:
1001 1002 value = undefined
1002 1003 name = tpl_global_var % name_full
1003 1004 lvals.append(tpl_name_val % (name, value))
1004 1005 if lvals:
1005 1006 lvals = '%s%s' % (indent, em_normal.join(lvals))
1006 1007 else:
1007 1008 lvals = ''
1008 1009
1009 1010 level = '%s %s\n' % (link, call)
1010 1011
1011 1012 if index is None:
1012 1013 return level
1013 1014 else:
1014 1015 return '%s%s' % (level, ''.join(
1015 1016 _format_traceback_lines(lnum, index, lines, Colors, lvals,
1016 1017 col_scheme)))
1017 1018
1018 1019 def prepare_chained_exception_message(self, cause):
1019 1020 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
1020 1021 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
1021 1022
1022 1023 if cause:
1023 1024 message = [[direct_cause]]
1024 1025 else:
1025 1026 message = [[exception_during_handling]]
1026 1027 return message
1027 1028
1028 1029 def prepare_header(self, etype, long_version=False):
1029 1030 colors = self.Colors # just a shorthand + quicker name lookup
1030 1031 colorsnormal = colors.Normal # used a lot
1031 1032 exc = '%s%s%s' % (colors.excName, etype, colorsnormal)
1033 width = min(75, get_terminal_size()[0])
1032 1034 if long_version:
1033 1035 # Header with the exception type, python version, and date
1034 1036 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
1035 1037 date = time.ctime(time.time())
1036 1038
1037 head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * 75, colorsnormal,
1038 exc, ' ' * (75 - len(str(etype)) - len(pyver)),
1039 pyver, date.rjust(75) )
1039 head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * width, colorsnormal,
1040 exc, ' ' * (width - len(str(etype)) - len(pyver)),
1041 pyver, date.rjust(width) )
1040 1042 head += "\nA problem occurred executing Python code. Here is the sequence of function" \
1041 1043 "\ncalls leading up to the error, with the most recent (innermost) call last."
1042 1044 else:
1043 1045 # Simplified header
1044 1046 head = '%s%s' % (exc, 'Traceback (most recent call last)'. \
1045 rjust(75 - len(str(etype))) )
1047 rjust(width - len(str(etype))) )
1046 1048
1047 1049 return head
1048 1050
1049 1051 def format_exception(self, etype, evalue):
1050 1052 colors = self.Colors # just a shorthand + quicker name lookup
1051 1053 colorsnormal = colors.Normal # used a lot
1052 1054 indent = ' ' * INDENT_SIZE
1053 1055 # Get (safely) a string form of the exception info
1054 1056 try:
1055 1057 etype_str, evalue_str = map(str, (etype, evalue))
1056 1058 except:
1057 1059 # User exception is improperly defined.
1058 1060 etype, evalue = str, sys.exc_info()[:2]
1059 1061 etype_str, evalue_str = map(str, (etype, evalue))
1060 1062 # ... and format it
1061 1063 exception = ['%s%s%s: %s' % (colors.excName, etype_str,
1062 1064 colorsnormal, py3compat.cast_unicode(evalue_str))]
1063 1065
1064 1066 if (not py3compat.PY3) and type(evalue) is types.InstanceType:
1065 1067 try:
1066 1068 names = [w for w in dir(evalue) if isinstance(w, py3compat.string_types)]
1067 1069 except:
1068 1070 # Every now and then, an object with funny internals blows up
1069 1071 # when dir() is called on it. We do the best we can to report
1070 1072 # the problem and continue
1071 1073 _m = '%sException reporting error (object with broken dir())%s:'
1072 1074 exception.append(_m % (colors.excName, colorsnormal))
1073 1075 etype_str, evalue_str = map(str, sys.exc_info()[:2])
1074 1076 exception.append('%s%s%s: %s' % (colors.excName, etype_str,
1075 1077 colorsnormal, py3compat.cast_unicode(evalue_str)))
1076 1078 names = []
1077 1079 for name in names:
1078 1080 value = text_repr(getattr(evalue, name))
1079 1081 exception.append('\n%s%s = %s' % (indent, name, value))
1080 1082
1081 1083 return exception
1082 1084
1083 1085 def format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_context, tb_offset):
1084 1086 """Formats the header, traceback and exception message for a single exception.
1085 1087
1086 1088 This may be called multiple times by Python 3 exception chaining
1087 1089 (PEP 3134).
1088 1090 """
1089 1091 # some locals
1090 1092 orig_etype = etype
1091 1093 try:
1092 1094 etype = etype.__name__
1093 1095 except AttributeError:
1094 1096 pass
1095 1097
1096 1098 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1097 1099 head = self.prepare_header(etype, self.long_header)
1098 1100 records = self.get_records(etb, number_of_lines_of_context, tb_offset)
1099 1101
1100 1102 if records is None:
1101 1103 return ""
1102 1104
1103 1105 last_unique, recursion_repeat = find_recursion(orig_etype, evalue, records)
1104 1106
1105 1107 frames = self.format_records(records, last_unique, recursion_repeat)
1106 1108
1107 1109 formatted_exception = self.format_exception(etype, evalue)
1108 1110 if records:
1109 1111 filepath, lnum = records[-1][1:3]
1110 1112 filepath = os.path.abspath(filepath)
1111 1113 ipinst = get_ipython()
1112 1114 if ipinst is not None:
1113 1115 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
1114 1116
1115 1117 return [[head] + frames + [''.join(formatted_exception[0])]]
1116 1118
1117 1119 def get_records(self, etb, number_of_lines_of_context, tb_offset):
1118 1120 try:
1119 1121 # Try the default getinnerframes and Alex's: Alex's fixes some
1120 1122 # problems, but it generates empty tracebacks for console errors
1121 1123 # (5 blanks lines) where none should be returned.
1122 1124 return _fixed_getinnerframes(etb, number_of_lines_of_context, tb_offset)
1123 1125 except:
1124 1126 # FIXME: I've been getting many crash reports from python 2.3
1125 1127 # users, traceable to inspect.py. If I can find a small test-case
1126 1128 # to reproduce this, I should either write a better workaround or
1127 1129 # file a bug report against inspect (if that's the real problem).
1128 1130 # So far, I haven't been able to find an isolated example to
1129 1131 # reproduce the problem.
1130 1132 inspect_error()
1131 1133 traceback.print_exc(file=self.ostream)
1132 1134 info('\nUnfortunately, your original traceback can not be constructed.\n')
1133 1135 return None
1134 1136
1135 1137 def get_parts_of_chained_exception(self, evalue):
1136 1138 def get_chained_exception(exception_value):
1137 1139 cause = getattr(exception_value, '__cause__', None)
1138 1140 if cause:
1139 1141 return cause
1140 1142 if getattr(exception_value, '__suppress_context__', False):
1141 1143 return None
1142 1144 return getattr(exception_value, '__context__', None)
1143 1145
1144 1146 chained_evalue = get_chained_exception(evalue)
1145 1147
1146 1148 if chained_evalue:
1147 1149 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
1148 1150
1149 1151 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
1150 1152 number_of_lines_of_context=5):
1151 1153 """Return a nice text document describing the traceback."""
1152 1154
1153 1155 formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
1154 1156 tb_offset)
1155 1157
1156 1158 colors = self.Colors # just a shorthand + quicker name lookup
1157 1159 colorsnormal = colors.Normal # used a lot
1158 head = '%s%s%s' % (colors.topline, '-' * 75, colorsnormal)
1160 head = '%s%s%s' % (colors.topline, '-' * min(75, get_terminal_size()[0]), colorsnormal)
1159 1161 structured_traceback_parts = [head]
1160 1162 if py3compat.PY3:
1161 1163 chained_exceptions_tb_offset = 0
1162 1164 lines_of_context = 3
1163 1165 formatted_exceptions = formatted_exception
1164 1166 exception = self.get_parts_of_chained_exception(evalue)
1165 1167 if exception:
1166 1168 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1167 1169 etype, evalue, etb = exception
1168 1170 else:
1169 1171 evalue = None
1170 1172 chained_exc_ids = set()
1171 1173 while evalue:
1172 1174 formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context,
1173 1175 chained_exceptions_tb_offset)
1174 1176 exception = self.get_parts_of_chained_exception(evalue)
1175 1177
1176 1178 if exception and not id(exception[1]) in chained_exc_ids:
1177 1179 chained_exc_ids.add(id(exception[1])) # trace exception to avoid infinite 'cause' loop
1178 1180 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1179 1181 etype, evalue, etb = exception
1180 1182 else:
1181 1183 evalue = None
1182 1184
1183 1185 # we want to see exceptions in a reversed order:
1184 1186 # the first exception should be on top
1185 1187 for formatted_exception in reversed(formatted_exceptions):
1186 1188 structured_traceback_parts += formatted_exception
1187 1189 else:
1188 1190 structured_traceback_parts += formatted_exception[0]
1189 1191
1190 1192 return structured_traceback_parts
1191 1193
1192 1194 def debugger(self, force=False):
1193 1195 """Call up the pdb debugger if desired, always clean up the tb
1194 1196 reference.
1195 1197
1196 1198 Keywords:
1197 1199
1198 1200 - force(False): by default, this routine checks the instance call_pdb
1199 1201 flag and does not actually invoke the debugger if the flag is false.
1200 1202 The 'force' option forces the debugger to activate even if the flag
1201 1203 is false.
1202 1204
1203 1205 If the call_pdb flag is set, the pdb interactive debugger is
1204 1206 invoked. In all cases, the self.tb reference to the current traceback
1205 1207 is deleted to prevent lingering references which hamper memory
1206 1208 management.
1207 1209
1208 1210 Note that each call to pdb() does an 'import readline', so if your app
1209 1211 requires a special setup for the readline completers, you'll have to
1210 1212 fix that by hand after invoking the exception handler."""
1211 1213
1212 1214 if force or self.call_pdb:
1213 1215 if self.pdb is None:
1214 1216 self.pdb = debugger.Pdb(
1215 1217 self.color_scheme_table.active_scheme_name)
1216 1218 # the system displayhook may have changed, restore the original
1217 1219 # for pdb
1218 1220 display_trap = DisplayTrap(hook=sys.__displayhook__)
1219 1221 with display_trap:
1220 1222 self.pdb.reset()
1221 1223 # Find the right frame so we don't pop up inside ipython itself
1222 1224 if hasattr(self, 'tb') and self.tb is not None:
1223 1225 etb = self.tb
1224 1226 else:
1225 1227 etb = self.tb = sys.last_traceback
1226 1228 while self.tb is not None and self.tb.tb_next is not None:
1227 1229 self.tb = self.tb.tb_next
1228 1230 if etb and etb.tb_next:
1229 1231 etb = etb.tb_next
1230 1232 self.pdb.botframe = etb.tb_frame
1231 1233 self.pdb.interaction(self.tb.tb_frame, self.tb)
1232 1234
1233 1235 if hasattr(self, 'tb'):
1234 1236 del self.tb
1235 1237
1236 1238 def handler(self, info=None):
1237 1239 (etype, evalue, etb) = info or sys.exc_info()
1238 1240 self.tb = etb
1239 1241 ostream = self.ostream
1240 1242 ostream.flush()
1241 1243 ostream.write(self.text(etype, evalue, etb))
1242 1244 ostream.write('\n')
1243 1245 ostream.flush()
1244 1246
1245 1247 # Changed so an instance can just be called as VerboseTB_inst() and print
1246 1248 # out the right info on its own.
1247 1249 def __call__(self, etype=None, evalue=None, etb=None):
1248 1250 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1249 1251 if etb is None:
1250 1252 self.handler()
1251 1253 else:
1252 1254 self.handler((etype, evalue, etb))
1253 1255 try:
1254 1256 self.debugger()
1255 1257 except KeyboardInterrupt:
1256 1258 print("\nKeyboardInterrupt")
1257 1259
1258 1260
1259 1261 #----------------------------------------------------------------------------
1260 1262 class FormattedTB(VerboseTB, ListTB):
1261 1263 """Subclass ListTB but allow calling with a traceback.
1262 1264
1263 1265 It can thus be used as a sys.excepthook for Python > 2.1.
1264 1266
1265 1267 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1266 1268
1267 1269 Allows a tb_offset to be specified. This is useful for situations where
1268 1270 one needs to remove a number of topmost frames from the traceback (such as
1269 1271 occurs with python programs that themselves execute other python code,
1270 1272 like Python shells). """
1271 1273
1272 1274 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1273 1275 ostream=None,
1274 1276 tb_offset=0, long_header=False, include_vars=False,
1275 1277 check_cache=None):
1276 1278
1277 1279 # NEVER change the order of this list. Put new modes at the end:
1278 1280 self.valid_modes = ['Plain', 'Context', 'Verbose']
1279 1281 self.verbose_modes = self.valid_modes[1:3]
1280 1282
1281 1283 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1282 1284 ostream=ostream, tb_offset=tb_offset,
1283 1285 long_header=long_header, include_vars=include_vars,
1284 1286 check_cache=check_cache)
1285 1287
1286 1288 # Different types of tracebacks are joined with different separators to
1287 1289 # form a single string. They are taken from this dict
1288 1290 self._join_chars = dict(Plain='', Context='\n', Verbose='\n')
1289 1291 # set_mode also sets the tb_join_char attribute
1290 1292 self.set_mode(mode)
1291 1293
1292 1294 def _extract_tb(self, tb):
1293 1295 if tb:
1294 1296 return traceback.extract_tb(tb)
1295 1297 else:
1296 1298 return None
1297 1299
1298 1300 def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5):
1299 1301 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1300 1302 mode = self.mode
1301 1303 if mode in self.verbose_modes:
1302 1304 # Verbose modes need a full traceback
1303 1305 return VerboseTB.structured_traceback(
1304 1306 self, etype, value, tb, tb_offset, number_of_lines_of_context
1305 1307 )
1306 1308 else:
1307 1309 # We must check the source cache because otherwise we can print
1308 1310 # out-of-date source code.
1309 1311 self.check_cache()
1310 1312 # Now we can extract and format the exception
1311 1313 elist = self._extract_tb(tb)
1312 1314 return ListTB.structured_traceback(
1313 1315 self, etype, value, elist, tb_offset, number_of_lines_of_context
1314 1316 )
1315 1317
1316 1318 def stb2text(self, stb):
1317 1319 """Convert a structured traceback (a list) to a string."""
1318 1320 return self.tb_join_char.join(stb)
1319 1321
1320 1322
1321 1323 def set_mode(self, mode=None):
1322 1324 """Switch to the desired mode.
1323 1325
1324 1326 If mode is not specified, cycles through the available modes."""
1325 1327
1326 1328 if not mode:
1327 1329 new_idx = (self.valid_modes.index(self.mode) + 1 ) % \
1328 1330 len(self.valid_modes)
1329 1331 self.mode = self.valid_modes[new_idx]
1330 1332 elif mode not in self.valid_modes:
1331 1333 raise ValueError('Unrecognized mode in FormattedTB: <' + mode + '>\n'
1332 1334 'Valid modes: ' + str(self.valid_modes))
1333 1335 else:
1334 1336 self.mode = mode
1335 1337 # include variable details only in 'Verbose' mode
1336 1338 self.include_vars = (self.mode == self.valid_modes[2])
1337 1339 # Set the join character for generating text tracebacks
1338 1340 self.tb_join_char = self._join_chars[self.mode]
1339 1341
1340 1342 # some convenient shortcuts
1341 1343 def plain(self):
1342 1344 self.set_mode(self.valid_modes[0])
1343 1345
1344 1346 def context(self):
1345 1347 self.set_mode(self.valid_modes[1])
1346 1348
1347 1349 def verbose(self):
1348 1350 self.set_mode(self.valid_modes[2])
1349 1351
1350 1352
1351 1353 #----------------------------------------------------------------------------
1352 1354 class AutoFormattedTB(FormattedTB):
1353 1355 """A traceback printer which can be called on the fly.
1354 1356
1355 1357 It will find out about exceptions by itself.
1356 1358
1357 1359 A brief example::
1358 1360
1359 1361 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1360 1362 try:
1361 1363 ...
1362 1364 except:
1363 1365 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1364 1366 """
1365 1367
1366 1368 def __call__(self, etype=None, evalue=None, etb=None,
1367 1369 out=None, tb_offset=None):
1368 1370 """Print out a formatted exception traceback.
1369 1371
1370 1372 Optional arguments:
1371 1373 - out: an open file-like object to direct output to.
1372 1374
1373 1375 - tb_offset: the number of frames to skip over in the stack, on a
1374 1376 per-call basis (this overrides temporarily the instance's tb_offset
1375 1377 given at initialization time. """
1376 1378
1377 1379 if out is None:
1378 1380 out = self.ostream
1379 1381 out.flush()
1380 1382 out.write(self.text(etype, evalue, etb, tb_offset))
1381 1383 out.write('\n')
1382 1384 out.flush()
1383 1385 # FIXME: we should remove the auto pdb behavior from here and leave
1384 1386 # that to the clients.
1385 1387 try:
1386 1388 self.debugger()
1387 1389 except KeyboardInterrupt:
1388 1390 print("\nKeyboardInterrupt")
1389 1391
1390 1392 def structured_traceback(self, etype=None, value=None, tb=None,
1391 1393 tb_offset=None, number_of_lines_of_context=5):
1392 1394 if etype is None:
1393 1395 etype, value, tb = sys.exc_info()
1394 1396 self.tb = tb
1395 1397 return FormattedTB.structured_traceback(
1396 1398 self, etype, value, tb, tb_offset, number_of_lines_of_context)
1397 1399
1398 1400
1399 1401 #---------------------------------------------------------------------------
1400 1402
1401 1403 # A simple class to preserve Nathan's original functionality.
1402 1404 class ColorTB(FormattedTB):
1403 1405 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1404 1406
1405 1407 def __init__(self, color_scheme='Linux', call_pdb=0, **kwargs):
1406 1408 FormattedTB.__init__(self, color_scheme=color_scheme,
1407 1409 call_pdb=call_pdb, **kwargs)
1408 1410
1409 1411
1410 1412 class SyntaxTB(ListTB):
1411 1413 """Extension which holds some state: the last exception value"""
1412 1414
1413 1415 def __init__(self, color_scheme='NoColor'):
1414 1416 ListTB.__init__(self, color_scheme)
1415 1417 self.last_syntax_error = None
1416 1418
1417 1419 def __call__(self, etype, value, elist):
1418 1420 self.last_syntax_error = value
1419 1421
1420 1422 ListTB.__call__(self, etype, value, elist)
1421 1423
1422 1424 def structured_traceback(self, etype, value, elist, tb_offset=None,
1423 1425 context=5):
1424 1426 # If the source file has been edited, the line in the syntax error can
1425 1427 # be wrong (retrieved from an outdated cache). This replaces it with
1426 1428 # the current value.
1427 1429 if isinstance(value, SyntaxError) \
1428 1430 and isinstance(value.filename, py3compat.string_types) \
1429 1431 and isinstance(value.lineno, int):
1430 1432 linecache.checkcache(value.filename)
1431 1433 newtext = ulinecache.getline(value.filename, value.lineno)
1432 1434 if newtext:
1433 1435 value.text = newtext
1434 1436 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1435 1437 tb_offset=tb_offset, context=context)
1436 1438
1437 1439 def clear_err_state(self):
1438 1440 """Return the current error state and clear it"""
1439 1441 e = self.last_syntax_error
1440 1442 self.last_syntax_error = None
1441 1443 return e
1442 1444
1443 1445 def stb2text(self, stb):
1444 1446 """Convert a structured traceback (a list) to a string."""
1445 1447 return ''.join(stb)
1446 1448
1447 1449
1448 1450 # some internal-use functions
1449 1451 def text_repr(value):
1450 1452 """Hopefully pretty robust repr equivalent."""
1451 1453 # this is pretty horrible but should always return *something*
1452 1454 try:
1453 1455 return pydoc.text.repr(value)
1454 1456 except KeyboardInterrupt:
1455 1457 raise
1456 1458 except:
1457 1459 try:
1458 1460 return repr(value)
1459 1461 except KeyboardInterrupt:
1460 1462 raise
1461 1463 except:
1462 1464 try:
1463 1465 # all still in an except block so we catch
1464 1466 # getattr raising
1465 1467 name = getattr(value, '__name__', None)
1466 1468 if name:
1467 1469 # ick, recursion
1468 1470 return text_repr(name)
1469 1471 klass = getattr(value, '__class__', None)
1470 1472 if klass:
1471 1473 return '%s instance' % text_repr(klass)
1472 1474 except KeyboardInterrupt:
1473 1475 raise
1474 1476 except:
1475 1477 return 'UNRECOVERABLE REPR FAILURE'
1476 1478
1477 1479
1478 1480 def eqrepr(value, repr=text_repr):
1479 1481 return '=%s' % repr(value)
1480 1482
1481 1483
1482 1484 def nullrepr(value, repr=text_repr):
1483 1485 return ''
@@ -1,156 +1,125 b''
1 1 # encoding: utf-8
2 2 """
3 3 Utilities for working with terminals.
4 4
5 5 Authors:
6 6
7 7 * Brian E. Granger
8 8 * Fernando Perez
9 9 * Alexander Belchenko (e-mail: bialix AT ukr.net)
10 10 """
11 11
12 12 #-----------------------------------------------------------------------------
13 13 # Copyright (C) 2008-2011 The IPython Development Team
14 14 #
15 15 # Distributed under the terms of the BSD License. The full license is in
16 16 # the file COPYING, distributed as part of this software.
17 17 #-----------------------------------------------------------------------------
18 18
19 19 #-----------------------------------------------------------------------------
20 20 # Imports
21 21 #-----------------------------------------------------------------------------
22 22
23 23 import os
24 24 import struct
25 25 import sys
26 26 import warnings
27 import backports.shutil_get_terminal_size
27 28
28 29 from . import py3compat
29 30
30 31 #-----------------------------------------------------------------------------
31 32 # Code
32 33 #-----------------------------------------------------------------------------
33 34
34 35 # This variable is part of the expected API of the module:
35 36 ignore_termtitle = True
36 37
37 38
38 39
39 40 if os.name == 'posix':
40 41 def _term_clear():
41 42 os.system('clear')
42 43 elif sys.platform == 'win32':
43 44 def _term_clear():
44 45 os.system('cls')
45 46 else:
46 47 def _term_clear():
47 48 pass
48 49
49 50
50 51
51 52 def toggle_set_term_title(val):
52 53 """Control whether set_term_title is active or not.
53 54
54 55 set_term_title() allows writing to the console titlebar. In embedded
55 56 widgets this can cause problems, so this call can be used to toggle it on
56 57 or off as needed.
57 58
58 59 The default state of the module is for the function to be disabled.
59 60
60 61 Parameters
61 62 ----------
62 63 val : bool
63 64 If True, set_term_title() actually writes to the terminal (using the
64 65 appropriate platform-specific module). If False, it is a no-op.
65 66 """
66 67 global ignore_termtitle
67 68 ignore_termtitle = not(val)
68 69
69 70
70 71 def _set_term_title(*args,**kw):
71 72 """Dummy no-op."""
72 73 pass
73 74
74 75
75 76 def _set_term_title_xterm(title):
76 77 """ Change virtual terminal title in xterm-workalikes """
77 78 sys.stdout.write('\033]0;%s\007' % title)
78 79
79 80 if os.name == 'posix':
80 81 TERM = os.environ.get('TERM','')
81 82 if TERM.startswith('xterm'):
82 83 _set_term_title = _set_term_title_xterm
83 84 elif sys.platform == 'win32':
84 85 try:
85 86 import ctypes
86 87
87 88 SetConsoleTitleW = ctypes.windll.kernel32.SetConsoleTitleW
88 89 SetConsoleTitleW.argtypes = [ctypes.c_wchar_p]
89 90
90 91 def _set_term_title(title):
91 92 """Set terminal title using ctypes to access the Win32 APIs."""
92 93 SetConsoleTitleW(title)
93 94 except ImportError:
94 95 def _set_term_title(title):
95 96 """Set terminal title using the 'title' command."""
96 97 global ignore_termtitle
97 98
98 99 try:
99 100 # Cannot be on network share when issuing system commands
100 101 curr = py3compat.getcwd()
101 102 os.chdir("C:")
102 103 ret = os.system("title " + title)
103 104 finally:
104 105 os.chdir(curr)
105 106 if ret:
106 107 # non-zero return code signals error, don't try again
107 108 ignore_termtitle = True
108 109
109 110
110 111 def set_term_title(title):
111 112 """Set terminal title using the necessary platform-dependent calls."""
112 113 if ignore_termtitle:
113 114 return
114 115 _set_term_title(title)
115 116
116 117
117 118 def freeze_term_title():
118 119 warnings.warn("This function is deprecated, use toggle_set_term_title()")
119 120 global ignore_termtitle
120 121 ignore_termtitle = True
121 122
122 123
123 if sys.platform == 'win32':
124 def get_terminal_size(defaultx=80, defaulty=25):
125 """Return size of current terminal console.
126
127 This function try to determine actual size of current working
128 console window and return tuple (sizex, sizey) if success,
129 or default size (defaultx, defaulty) otherwise.
130
131 Dependencies: ctypes should be installed.
132
133 Author: Alexander Belchenko (e-mail: bialix AT ukr.net)
134 """
135 try:
136 import ctypes
137 except ImportError:
138 return defaultx, defaulty
139
140 h = ctypes.windll.kernel32.GetStdHandle(-11)
141 csbi = ctypes.create_string_buffer(22)
142 res = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
143
144 if res:
145 (bufx, bufy, curx, cury, wattr,
146 left, top, right, bottom, maxx, maxy) = struct.unpack(
147 "hhhhHhhhhhh", csbi.raw)
148 sizex = right - left + 1
149 sizey = bottom - top + 1
150 return (sizex, sizey)
151 else:
152 return (defaultx, defaulty)
153 else:
154 def get_terminal_size(defaultx=80, defaulty=25):
155 return defaultx, defaulty
156
124 def get_terminal_size(defaultx=80, defaulty=25):
125 return backports.shutil_get_terminal_size.get_terminal_size((defaultx, defaulty))
@@ -1,297 +1,298 b''
1 1 #!/usr/bin/env python
2 2 # -*- coding: utf-8 -*-
3 3 """Setup script for IPython.
4 4
5 5 Under Posix environments it works like a typical setup.py script.
6 6 Under Windows, the command sdist is not supported, since IPython
7 7 requires utilities which are not available under Windows."""
8 8
9 9 #-----------------------------------------------------------------------------
10 10 # Copyright (c) 2008-2011, IPython Development Team.
11 11 # Copyright (c) 2001-2007, Fernando Perez <fernando.perez@colorado.edu>
12 12 # Copyright (c) 2001, Janko Hauser <jhauser@zscout.de>
13 13 # Copyright (c) 2001, Nathaniel Gray <n8gray@caltech.edu>
14 14 #
15 15 # Distributed under the terms of the Modified BSD License.
16 16 #
17 17 # The full license is in the file COPYING.rst, distributed with this software.
18 18 #-----------------------------------------------------------------------------
19 19
20 20 #-----------------------------------------------------------------------------
21 21 # Minimal Python version sanity check
22 22 #-----------------------------------------------------------------------------
23 23 from __future__ import print_function
24 24
25 25 import sys
26 26
27 27 # This check is also made in IPython/__init__, don't forget to update both when
28 28 # changing Python version requirements.
29 29 v = sys.version_info
30 30 if v[:2] < (2,7) or (v[0] >= 3 and v[:2] < (3,3)):
31 31 error = "ERROR: IPython requires Python version 2.7 or 3.3 or above."
32 32 print(error, file=sys.stderr)
33 33 sys.exit(1)
34 34
35 35 PY3 = (sys.version_info[0] >= 3)
36 36
37 37 # At least we're on the python version we need, move on.
38 38
39 39 #-------------------------------------------------------------------------------
40 40 # Imports
41 41 #-------------------------------------------------------------------------------
42 42
43 43 # Stdlib imports
44 44 import os
45 45
46 46 from glob import glob
47 47
48 48 # BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
49 49 # update it when the contents of directories change.
50 50 if os.path.exists('MANIFEST'): os.remove('MANIFEST')
51 51
52 52 from distutils.core import setup
53 53
54 54 # Our own imports
55 55 from setupbase import target_update
56 56
57 57 from setupbase import (
58 58 setup_args,
59 59 find_packages,
60 60 find_package_data,
61 61 check_package_data_first,
62 62 find_entry_points,
63 63 build_scripts_entrypt,
64 64 find_data_files,
65 65 git_prebuild,
66 66 install_symlinked,
67 67 install_lib_symlink,
68 68 install_scripts_for_symlink,
69 69 unsymlink,
70 70 )
71 71
72 72 isfile = os.path.isfile
73 73 pjoin = os.path.join
74 74
75 75 #-------------------------------------------------------------------------------
76 76 # Handle OS specific things
77 77 #-------------------------------------------------------------------------------
78 78
79 79 if os.name in ('nt','dos'):
80 80 os_name = 'windows'
81 81 else:
82 82 os_name = os.name
83 83
84 84 # Under Windows, 'sdist' has not been supported. Now that the docs build with
85 85 # Sphinx it might work, but let's not turn it on until someone confirms that it
86 86 # actually works.
87 87 if os_name == 'windows' and 'sdist' in sys.argv:
88 88 print('The sdist command is not available under Windows. Exiting.')
89 89 sys.exit(1)
90 90
91 91
92 92 #-------------------------------------------------------------------------------
93 93 # Things related to the IPython documentation
94 94 #-------------------------------------------------------------------------------
95 95
96 96 # update the manuals when building a source dist
97 97 if len(sys.argv) >= 2 and sys.argv[1] in ('sdist','bdist_rpm'):
98 98
99 99 # List of things to be updated. Each entry is a triplet of args for
100 100 # target_update()
101 101 to_update = [
102 102 ('docs/man/ipython.1.gz',
103 103 ['docs/man/ipython.1'],
104 104 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz'),
105 105 ]
106 106
107 107
108 108 [ target_update(*t) for t in to_update ]
109 109
110 110 #---------------------------------------------------------------------------
111 111 # Find all the packages, package data, and data_files
112 112 #---------------------------------------------------------------------------
113 113
114 114 packages = find_packages()
115 115 package_data = find_package_data()
116 116
117 117 data_files = find_data_files()
118 118
119 119 setup_args['packages'] = packages
120 120 setup_args['package_data'] = package_data
121 121 setup_args['data_files'] = data_files
122 122
123 123 #---------------------------------------------------------------------------
124 124 # custom distutils commands
125 125 #---------------------------------------------------------------------------
126 126 # imports here, so they are after setuptools import if there was one
127 127 from distutils.command.sdist import sdist
128 128 from distutils.command.upload import upload
129 129
130 130 class UploadWindowsInstallers(upload):
131 131
132 132 description = "Upload Windows installers to PyPI (only used from tools/release_windows.py)"
133 133 user_options = upload.user_options + [
134 134 ('files=', 'f', 'exe file (or glob) to upload')
135 135 ]
136 136 def initialize_options(self):
137 137 upload.initialize_options(self)
138 138 meta = self.distribution.metadata
139 139 base = '{name}-{version}'.format(
140 140 name=meta.get_name(),
141 141 version=meta.get_version()
142 142 )
143 143 self.files = os.path.join('dist', '%s.*.exe' % base)
144 144
145 145 def run(self):
146 146 for dist_file in glob(self.files):
147 147 self.upload_file('bdist_wininst', 'any', dist_file)
148 148
149 149 setup_args['cmdclass'] = {
150 150 'build_py': \
151 151 check_package_data_first(git_prebuild('IPython')),
152 152 'sdist' : git_prebuild('IPython', sdist),
153 153 'upload_wininst' : UploadWindowsInstallers,
154 154 'symlink': install_symlinked,
155 155 'install_lib_symlink': install_lib_symlink,
156 156 'install_scripts_sym': install_scripts_for_symlink,
157 157 'unsymlink': unsymlink,
158 158 }
159 159
160 160
161 161 #---------------------------------------------------------------------------
162 162 # Handle scripts, dependencies, and setuptools specific things
163 163 #---------------------------------------------------------------------------
164 164
165 165 # For some commands, use setuptools. Note that we do NOT list install here!
166 166 # If you want a setuptools-enhanced install, just run 'setupegg.py install'
167 167 needs_setuptools = set(('develop', 'release', 'bdist_egg', 'bdist_rpm',
168 168 'bdist', 'bdist_dumb', 'bdist_wininst', 'bdist_wheel',
169 169 'egg_info', 'easy_install', 'upload', 'install_egg_info',
170 170 ))
171 171
172 172 if len(needs_setuptools.intersection(sys.argv)) > 0:
173 173 import setuptools
174 174
175 175 # This dict is used for passing extra arguments that are setuptools
176 176 # specific to setup
177 177 setuptools_extra_args = {}
178 178
179 179 # setuptools requirements
180 180
181 181 extras_require = dict(
182 182 parallel = ['ipyparallel'],
183 183 qtconsole = ['qtconsole'],
184 184 doc = ['Sphinx>=1.3'],
185 185 test = ['nose>=0.10.1', 'requests', 'testpath', 'pygments'],
186 186 terminal = [],
187 187 kernel = ['ipykernel'],
188 188 nbformat = ['nbformat'],
189 189 notebook = ['notebook', 'ipywidgets'],
190 190 nbconvert = ['nbconvert'],
191 191 )
192 192 install_requires = [
193 193 'setuptools>=18.5',
194 194 'decorator',
195 195 'pickleshare',
196 196 'simplegeneric>0.8',
197 197 'traitlets',
198 198 'prompt_toolkit>=0.58',
199 199 'pygments',
200 'backports.shutil_get_terminal_size',
200 201 ]
201 202
202 203 # Platform-specific dependencies:
203 204 # This is the correct way to specify these,
204 205 # but requires pip >= 6. pip < 6 ignores these.
205 206
206 207 extras_require.update({
207 208 ':sys_platform != "win32"': ['pexpect'],
208 209 ':sys_platform == "darwin"': ['appnope'],
209 210 ':sys_platform == "win32"': ['colorama'],
210 211 'test:python_version == "2.7"': ['mock'],
211 212 })
212 213 # FIXME: re-specify above platform dependencies for pip < 6
213 214 # These would result in non-portable bdists.
214 215 if not any(arg.startswith('bdist') for arg in sys.argv):
215 216 if sys.version_info < (3, 3):
216 217 extras_require['test'].append('mock')
217 218
218 219 if sys.platform == 'darwin':
219 220 install_requires.extend(['appnope'])
220 221 have_readline = False
221 222 try:
222 223 import readline
223 224 except ImportError:
224 225 pass
225 226 else:
226 227 if 'libedit' not in readline.__doc__:
227 228 have_readline = True
228 229 if not have_readline:
229 230 install_requires.extend(['gnureadline'])
230 231
231 232 if sys.platform.startswith('win'):
232 233 extras_require['terminal'].append('pyreadline>=2.0')
233 234 else:
234 235 install_requires.append('pexpect')
235 236
236 237 # workaround pypa/setuptools#147, where setuptools misspells
237 238 # platform_python_implementation as python_implementation
238 239 if 'setuptools' in sys.modules:
239 240 for key in list(extras_require):
240 241 if 'platform_python_implementation' in key:
241 242 new_key = key.replace('platform_python_implementation', 'python_implementation')
242 243 extras_require[new_key] = extras_require.pop(key)
243 244
244 245 everything = set()
245 246 for key, deps in extras_require.items():
246 247 if ':' not in key:
247 248 everything.update(deps)
248 249 extras_require['all'] = everything
249 250
250 251 if 'setuptools' in sys.modules:
251 252 setuptools_extra_args['zip_safe'] = False
252 253 setuptools_extra_args['entry_points'] = {
253 254 'console_scripts': find_entry_points(),
254 255 'pygments.lexers': [
255 256 'ipythonconsole = IPython.lib.lexers:IPythonConsoleLexer',
256 257 'ipython = IPython.lib.lexers:IPythonLexer',
257 258 'ipython3 = IPython.lib.lexers:IPython3Lexer',
258 259 ],
259 260 }
260 261 setup_args['extras_require'] = extras_require
261 262 requires = setup_args['install_requires'] = install_requires
262 263
263 264 # Script to be run by the windows binary installer after the default setup
264 265 # routine, to add shortcuts and similar windows-only things. Windows
265 266 # post-install scripts MUST reside in the scripts/ dir, otherwise distutils
266 267 # doesn't find them.
267 268 if 'bdist_wininst' in sys.argv:
268 269 if len(sys.argv) > 2 and \
269 270 ('sdist' in sys.argv or 'bdist_rpm' in sys.argv):
270 271 print("ERROR: bdist_wininst must be run alone. Exiting.", file=sys.stderr)
271 272 sys.exit(1)
272 273 setup_args['data_files'].append(
273 274 ['Scripts', ('scripts/ipython.ico', 'scripts/ipython_nb.ico')])
274 275 setup_args['scripts'] = [pjoin('scripts','ipython_win_post_install.py')]
275 276 setup_args['options'] = {"bdist_wininst":
276 277 {"install_script":
277 278 "ipython_win_post_install.py"}}
278 279
279 280 else:
280 281 # scripts has to be a non-empty list, or install_scripts isn't called
281 282 setup_args['scripts'] = [e.split('=')[0].strip() for e in find_entry_points()]
282 283
283 284 setup_args['cmdclass']['build_scripts'] = build_scripts_entrypt
284 285
285 286 #---------------------------------------------------------------------------
286 287 # Do the actual setup now
287 288 #---------------------------------------------------------------------------
288 289
289 290 setup_args.update(setuptools_extra_args)
290 291
291 292
292 293
293 294 def main():
294 295 setup(**setup_args)
295 296
296 297 if __name__ == '__main__':
297 298 main()
General Comments 0
You need to be logged in to leave comments. Login now