)", " \\1 ", html)
- # weird 2-part syntax is a workaround for hard-to-grep text.
- html = html.replace(
- "A problem occurred in a Python script. "
- "Here is the sequence of",
- "",
- )
- html = html.replace(
- "function calls leading up to the error, "
- "in the order they occurred. ",
- " ",
- )
- # remove hardcoded fonts
- html = html.replace("\n", " ")
- html = (
- f"" + html + ""
- )
- tb_text = html
- else:
- # if we don't need HTML, just use traceback
- tb_text = "".join(traceback.format_exception(*info))
- # resets to default behavior
- if np_imported:
- np.set_string_function(None)
- return tb_text
+ if sys.version_info < (3, 11):
+ import cgitb
+
+ # cgitb does not support error chaining...
+ # see https://peps.python.org/pep-3134/#enhanced-reporting
+ # this is a workaround
+ def cgitb_chain(exc: Exception) -> Generator[str, None, None]:
+ """Recurse through exception stack and chain cgitb_html calls."""
+ if exc.__cause__:
+ yield from cgitb_chain(exc.__cause__)
+ yield (
+ '
The above exception was '
+ "the direct cause of the following exception: "
+ )
+ elif exc.__context__:
+ yield from cgitb_chain(exc.__context__)
+ yield (
+ '
During handling of the '
+ "above exception, another exception occurred: "
+ )
+ yield cgitb_html(exc)
+
+ def cgitb_html(exc: Exception) -> str:
+ """Format exception with cgitb.html."""
+ info = (type(exc), exc, exc.__traceback__)
+ return cgitb.html(info)
+
+ def format_exc_info(info: ExcInfo, as_html: bool, color=None) -> str:
+ # avoid verbose printing of the array data
+ with np.printoptions(precision=5, threshold=10, edgeitems=2):
+ if as_html:
+ html = "\n".join(cgitb_chain(info[1]))
+ # cgitb has a lot of hardcoded colors that don't work for us
+ # remove bgcolor, and let theme handle it
+ html = re.sub('bgcolor="#.*"', "", html)
+ # remove superfluous whitespace
+ html = html.replace(" \n", "\n")
+ # but retain it around the bits
+ html = re.sub(r"()", " \\1 ", html)
+ # weird 2-part syntax is a workaround for hard-to-grep text.
+ html = html.replace(
+ "A problem occurred in a Python script. "
+ "Here is the sequence of",
+ "",
+ )
+ html = html.replace(
+ "function calls leading up to the error, "
+ "in the order they occurred. ",
+ " ",
+ )
+ # remove hardcoded fonts
+ html = html.replace('face="helvetica, arial"', "")
+ html = (
+ f"" + html + ""
+ )
+ tb_text = html
+ else:
+ # if we don't need HTML, just use traceback
+ tb_text = "".join(traceback.format_exception(*info))
+ return tb_text
+
+ else:
+
+ def format_exc_info(info: ExcInfo, as_html: bool, color=None) -> str:
+ # avoid verbose printing of the array data
+ with np.printoptions(precision=5, threshold=10, edgeitems=2):
+ tb_text = "".join(traceback.format_exception(*info))
+ if as_html:
+ tb_text = "" + tb_text + " "
+ return tb_text
return format_exc_info
@@ -273,8 +270,7 @@ def format_exc_info(exc: Exception, as_html: bool, color=None) -> str:
def ansi2html(
ansi_string: str, styles: dict[int, dict[str, str]] = ANSI_STYLES
) -> Generator[str, None, None]:
- """
- Convert ansi string to colored HTML
+ """Convert ansi string to colored HTML
Parameters
----------
@@ -292,7 +288,7 @@ def ansi2html(
previous_end = 0
in_span = False
ansi_codes = []
- ansi_finder = re.compile("\033\\[" "([\\d;]*)" "([a-zA-z])")
+ ansi_finder = re.compile("\033\\[([\\d;]*)([a-zA-Z])")
for match in ansi_finder.finditer(ansi_string):
yield ansi_string[previous_end : match.start()]
previous_end = match.end()
@@ -329,7 +325,7 @@ def ansi2html(
for k in ansi_codes
if k in styles
]
- yield '' % "; ".join(style)
+ yield ''.format("; ".join(style))
in_span = True
diff --git a/tabulous/widgets/_mainwindow.py b/tabulous/widgets/_mainwindow.py
index 56ef045..3dde5de 100644
--- a/tabulous/widgets/_mainwindow.py
+++ b/tabulous/widgets/_mainwindow.py
@@ -350,9 +350,9 @@ def add_layer(self, input: TableBase, *, update: bool = False):
"""Add any table object to the viewer."""
if table := self.current_table:
table_has_focus = table.native._qtable_view.hasFocus()
+ table._qwidget._qtable_view._close_editor()
else:
table_has_focus = False
- self.current_table._qwidget._qtable_view._close_editor()
if (
update
and (table := self.tables.get(input.name, None))
| |