Refactor `Group` to subclass `traceback.StackSummary`
Closed this issue · 0 comments
teymour-aldridge commented
werkzeug/src/werkzeug/debug/tbtools.py
Lines 339 to 419 in 31f7600
class Group: | |
"""A group of frames for an exception in a traceback. If the | |
exception has a ``__cause__`` or ``__context__``, there are multiple | |
exception groups. | |
""" | |
def __init__(self, exc_type, exc_value, tb): | |
self.exc_type = exc_type | |
self.exc_value = exc_value | |
self.info = None | |
if exc_value.__cause__ is not None: | |
self.info = ( | |
"The above exception was the direct cause of the following exception" | |
) | |
elif exc_value.__context__ is not None: | |
self.info = ( | |
"During handling of the above exception, another exception occurred" | |
) | |
self.frames = [] | |
while tb is not None: | |
self.frames.append(Frame(exc_type, exc_value, tb)) | |
tb = tb.tb_next | |
def filter_hidden_frames(self): | |
new_frames = [] | |
hidden = False | |
for frame in self.frames: | |
hide = frame.hide | |
if hide in ("before", "before_and_this"): | |
new_frames = [] | |
hidden = False | |
if hide == "before_and_this": | |
continue | |
elif hide in ("reset", "reset_and_this"): | |
hidden = False | |
if hide == "reset_and_this": | |
continue | |
elif hide in ("after", "after_and_this"): | |
hidden = True | |
if hide == "after_and_this": | |
continue | |
elif hide or hidden: | |
continue | |
new_frames.append(frame) | |
# if we only have one frame and that frame is from the codeop | |
# module, remove it. | |
if len(new_frames) == 1 and self.frames[0].module == "codeop": | |
del self.frames[:] | |
# if the last frame is missing something went terrible wrong :( | |
elif self.frames[-1] in new_frames: | |
self.frames[:] = new_frames | |
@property | |
def exception(self): | |
"""String representation of the exception.""" | |
buf = traceback.format_exception_only(self.exc_type, self.exc_value) | |
rv = "".join(buf).strip() | |
return _to_str(rv, "utf-8", "replace") | |
def render(self, mark_lib=True): | |
out = [] | |
if self.info is not None: | |
out.append(f'<li><div class="exc-divider">{self.info}:</div>') | |
for frame in self.frames: | |
title = f' title="{escape(frame.info)}"' if frame.info else "" | |
out.append(f"<li{title}>{frame.render(mark_lib=mark_lib)}") | |
return "\n".join(out) | |
def render_text(self): | |
out = [] | |
if self.info is not None: | |
out.append(f"\n{self.info}:\n") | |
out.append("Traceback (most recent call last):") | |
for frame in self.frames: | |
out.append(frame.render_text()) | |
out.append(self.exception) | |
return "\n".join(out) |