1 # Copyright 2015 Google Inc. All Rights Reserved.
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
21 def PrintFormattedException(msg
=None):
22 exception_class
, exception
, tb
= sys
.exc_info()
24 def _GetFinalFrame(tb_level
):
25 while tb_level
.tb_next
:
26 tb_level
= tb_level
.tb_next
27 return tb_level
.tb_frame
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
)
36 print >> sys
.stderr
, msg
38 _PrintFormattedTrace(processed_tb
, frame
, exception_string
)
40 def PrintFormattedFrame(frame
, exception_string
=None):
41 _PrintFormattedTrace(traceback
.extract_stack(frame
), frame
, exception_string
)
44 def _PrintFormattedTrace(processed_tb
, frame
, exception_string
=None):
45 """Prints an Exception in a more useful format than the default.
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
59 # Format the exception.
61 print >> sys
.stderr
, exception_string
64 local_variables
= [(variable
, value
) for variable
, value
in
65 frame
.f_locals
.iteritems() if variable
!= 'self']
67 print >> sys
.stderr
, 'Locals:'
69 longest_variable
= max(len(v
) for v
, _
in local_variables
)
70 for variable
, value
in sorted(local_variables
):
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
)
80 print >> sys
.stderr
, ' No locals!'
86 def _AbbreviateMiddleOfString(target
, middle
, max_length
):
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')
92 if len(target
) <= max_length
:
94 half_length
= (max_length
- len(middle
)) / 2.
95 return (target
[:int(math
.floor(half_length
))] + middle
+
96 target
[-int(math
.ceil(half_length
)):])