OLD | NEW |
| (Empty) |
1 # Copyright 2015 Google Inc. All Rights Reserved. | |
2 # | |
3 # Licensed under the Apache License, Version 2.0 (the "License"); | |
4 # you may not use this file except in compliance with the License. | |
5 # You may obtain a copy of the License at | |
6 # | |
7 # http://www.apache.org/licenses/LICENSE-2.0 | |
8 # | |
9 # Unless required by applicable law or agreed to in writing, software | |
10 # distributed under the License is distributed on an "AS IS" BASIS, | |
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 # See the License for the specific language governing permissions and | |
13 # limitations under the License. | |
14 | |
15 import math | |
16 import os | |
17 import sys | |
18 import traceback | |
19 | |
20 | |
21 def PrintFormattedException(msg=None): | |
22 exception_class, exception, tb = sys.exc_info() | |
23 | |
24 def _GetFinalFrame(tb_level): | |
25 while tb_level.tb_next: | |
26 tb_level = tb_level.tb_next | |
27 return tb_level.tb_frame | |
28 | |
29 processed_tb = traceback.extract_tb(tb) | |
30 frame = _GetFinalFrame(tb) | |
31 exception_list = traceback.format_exception_only(exception_class, exception) | |
32 exception_string = '\n'.join(l.strip() for l in exception_list) | |
33 | |
34 if msg: | |
35 print >> sys.stderr | |
36 print >> sys.stderr, msg | |
37 | |
38 _PrintFormattedTrace(processed_tb, frame, exception_string) | |
39 | |
40 def PrintFormattedFrame(frame, exception_string=None): | |
41 _PrintFormattedTrace(traceback.extract_stack(frame), frame, exception_string) | |
42 | |
43 | |
44 def _PrintFormattedTrace(processed_tb, frame, exception_string=None): | |
45 """Prints an Exception in a more useful format than the default. | |
46 """ | |
47 print >> sys.stderr | |
48 | |
49 # Format the traceback. | |
50 base_dir = os.path.dirname(__file__) | |
51 print >> sys.stderr, 'Traceback (most recent call last):' | |
52 for filename, line, function, text in processed_tb: | |
53 filename = os.path.abspath(filename) | |
54 if filename.startswith(base_dir): | |
55 filename = filename[len(base_dir)+1:] | |
56 print >> sys.stderr, ' %s at %s:%d' % (function, filename, line) | |
57 print >> sys.stderr, ' %s' % text | |
58 | |
59 # Format the exception. | |
60 if exception_string: | |
61 print >> sys.stderr, exception_string | |
62 | |
63 # Format the locals. | |
64 local_variables = [(variable, value) for variable, value in | |
65 frame.f_locals.iteritems() if variable != 'self'] | |
66 print >> sys.stderr | |
67 print >> sys.stderr, 'Locals:' | |
68 if local_variables: | |
69 longest_variable = max(len(v) for v, _ in local_variables) | |
70 for variable, value in sorted(local_variables): | |
71 value = repr(value) | |
72 possibly_truncated_value = _AbbreviateMiddleOfString(value, ' ... ', 1024) | |
73 truncation_indication = '' | |
74 if len(possibly_truncated_value) != len(value): | |
75 truncation_indication = ' (truncated)' | |
76 print >> sys.stderr, ' %s: %s%s' % (variable.ljust(longest_variable + 1), | |
77 possibly_truncated_value, | |
78 truncation_indication) | |
79 else: | |
80 print >> sys.stderr, ' No locals!' | |
81 | |
82 print >> sys.stderr | |
83 sys.stderr.flush() | |
84 | |
85 | |
86 def _AbbreviateMiddleOfString(target, middle, max_length): | |
87 if max_length < 0: | |
88 raise ValueError('Must provide positive max_length') | |
89 if len(middle) > max_length: | |
90 raise ValueError('middle must not be greater than max_length') | |
91 | |
92 if len(target) <= max_length: | |
93 return target | |
94 half_length = (max_length - len(middle)) / 2. | |
95 return (target[:int(math.floor(half_length))] + middle + | |
96 target[-int(math.ceil(half_length)):]) | |
OLD | NEW |