@@ -124,7 +124,44 @@ def format_exc_info(etype, evalue, tb, style='plaintext', add_summary='auto',
124
124
125
125
keyword args like stackprinter.format()
126
126
"""
127
+ msg = ''
127
128
try :
129
+ # First, recursively format any chained exceptions (exceptions during whose handling
130
+ # the given one happened).
131
+ # TODO: refactor this whole messy function to return a more... structured datastructure
132
+ # before assembling a string, so that e.g. a summary of the whole chain can be shown at
133
+ # the end.
134
+ context = getattr (evalue , '__context__' , None )
135
+ cause = getattr (evalue , '__cause__' , None )
136
+ suppress_context = getattr (evalue , '__suppress_context__' , False )
137
+ if cause :
138
+ chained_exc = cause
139
+ chain_hint = ("\n \n The above exception was the direct cause "
140
+ "of the following exception:\n \n " )
141
+ elif context and not suppress_context :
142
+ chained_exc = context
143
+ chain_hint = ("\n \n While handling the above exception, "
144
+ "another exception occurred:\n \n " )
145
+ else :
146
+ chained_exc = None
147
+
148
+ if chained_exc :
149
+ msg += format_exc_info (chained_exc .__class__ ,
150
+ chained_exc ,
151
+ chained_exc .__traceback__ ,
152
+ style = style ,
153
+ add_summary = add_summary ,
154
+ reverse = reverse ,
155
+ ** kwargs )
156
+
157
+ if style == 'plaintext' :
158
+ msg += chain_hint
159
+ else :
160
+ sc = getattr (colorschemes , style )
161
+ clr = get_ansi_tpl (* sc .colors ['exception_type' ])
162
+ msg += clr % chain_hint
163
+
164
+ # Now, actually do some formatting:
128
165
msgs = []
129
166
if tb :
130
167
frameinfos = [ex .get_info (tb_ ) for tb_ in _walk_traceback (tb )]
@@ -148,7 +185,7 @@ def format_exc_info(etype, evalue, tb, style='plaintext', add_summary='auto',
148
185
if reverse :
149
186
msgs = reversed (msgs )
150
187
151
- msg = '' .join (msgs )
188
+ msg + = '' .join (msgs )
152
189
153
190
except Exception as exc :
154
191
our_tb = traceback .format_exception (exc .__class__ ,
0 commit comments