diff --git a/sandbox/grist/gencode.py b/sandbox/grist/gencode.py index 75aeb1b7..12801ad6 100644 --- a/sandbox/grist/gencode.py +++ b/sandbox/grist/gencode.py @@ -15,6 +15,7 @@ The schema for grist data is: "formula": , } """ +import linecache import re import imp from collections import OrderedDict @@ -194,6 +195,17 @@ def _is_special_table(table_id): def exec_module_text(module_text): # pylint: disable=exec-used - mod = imp.new_module("usercode") - exec(module_text, mod.__dict__) + filename = "usercode" + mod = imp.new_module(filename) + + # Ensure that source lines show in tracebacks + linecache.cache[filename] = ( + len(module_text), + None, + [line + '\n' for line in module_text.splitlines()], + filename, + ) + + code_obj = compile(module_text, filename, "exec") + exec(code_obj, mod.__dict__) return mod diff --git a/sandbox/grist/test_formula_error.py b/sandbox/grist/test_formula_error.py index e2605c28..791568f7 100644 --- a/sandbox/grist/test_formula_error.py +++ b/sandbox/grist/test_formula_error.py @@ -66,7 +66,14 @@ else: r"TypeError: SQRT\(\) takes 1 positional argument but 2 were given") self.assertFormulaError(self.engine.get_formula_error('Math', 'built_in_formula', 3), - TypeError, "'int' object is not iterable") + TypeError, "'int' object is not iterable", + textwrap.dedent( + r""" + File "usercode", line \d+, in built_in_formula + return max\(5\) + TypeError: 'int' object is not iterable + """ + )) self.assertFormulaError(self.engine.get_formula_error('Math', 'syntax_err', 3), SyntaxError, "invalid syntax on line 5 col 9") @@ -76,7 +83,13 @@ else: self.assertFormulaError(self.engine.get_formula_error('Math', 'other_err', 3), TypeError, "'int' object is not iterable", - r"line \d+, in other_err") + textwrap.dedent( + r""" + File "usercode", line \d+, in other_err + if sum\(3, 5\) > 6: + TypeError: 'int' object is not iterable + """ + )) self.assertFormulaError(self.engine.get_formula_error('Math', 'custom_err', 3), Exception, "hello")