Skip to content

Commit 5b11a0e

Browse files
Improved Error in :mod:.utils.tex_file_writing (#2574)
* Better Error and insight * Do not use keywords as identifiers * add_tests * Nasty comma * Windows does its own thing * Use os.path.join for windows * Do not log path * Include Insights * Full stop. Co-authored-by: Darylgolden <[email protected]> * Full stop to test data. Co-authored-by: Darylgolden <[email protected]>
1 parent d202d26 commit 5b11a0e

File tree

4 files changed

+72
-33
lines changed

4 files changed

+72
-33
lines changed

manim/utils/tex_file_writing.py

Lines changed: 32 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ def generate_tex_file(expression, environment=None, tex_template=None):
8484

8585
result = os.path.join(tex_dir, tex_hash(output)) + ".tex"
8686
if not os.path.exists(result):
87-
logger.info('Writing "{}" to {}'.format("".join(expression), result))
87+
logger.info(f"Writing {expression} to %(path)s", {"path": f"{result}"})
8888
with open(result, "w", encoding="utf-8") as outfile:
8989
outfile.write(output)
9090
return result
@@ -142,11 +142,16 @@ def tex_compilation_command(tex_compiler, output_format, tex_file, tex_dir):
142142
return " ".join(commands)
143143

144144

145-
def insight_inputenc_error(match):
146-
code_point = chr(int(match[1], 16))
145+
def insight_inputenc_error(matching):
146+
code_point = chr(int(matching[1], 16))
147147
name = unicodedata.name(code_point)
148-
yield f"TexTemplate does not support character '{name}' (U+{match[1]})"
149-
yield "See the documentation for manim.mobject.svg.tex_mobject for details on using a custom TexTemplate"
148+
yield f"TexTemplate does not support character '{name}' (U+{matching[1]})."
149+
yield "See the documentation for manim.mobject.svg.tex_mobject for details on using a custom TexTemplate."
150+
151+
152+
def insight_package_not_found_error(matching):
153+
yield f"You do not have package {matching[1]} installed."
154+
yield f"Install {matching[1]} it using your LaTeX package manager, or check for typos."
150155

151156

152157
def compile_tex(tex_file, tex_compiler, output_format):
@@ -260,6 +265,10 @@ def print_all_tex_errors(log_file, tex_compiler, tex_file):
260265
r"inputenc Error: Unicode character (?:.*) \(U\+([0-9a-fA-F]+)\)",
261266
insight_inputenc_error,
262267
),
268+
(
269+
r"LaTeX Error: File `(.*?[clsty])' not found",
270+
insight_package_not_found_error,
271+
),
263272
]
264273

265274

@@ -286,36 +295,26 @@ def print_tex_error(tex_compilation_log, error_start_index, tex_source):
286295
if line_of_tex_error >= len(tex_source):
287296
return None
288297

289-
# all lines numbers containing '\begin{' or '\end{' - except the Manim added center and document tags
290-
env_markers_indices = [
291-
idx
292-
for idx, log_line in enumerate(tex_source)
293-
if any(marker in log_line for marker in [r"\begin{", r"\end{"])
294-
][2:-2]
295-
296-
context = "Context of error:\n\n"
297-
if line_of_tex_error in env_markers_indices:
298-
context += "".join(tex_source[line_of_tex_error - 1 : line_of_tex_error + 1])
298+
context = ["Context of error: \n"]
299+
if line_of_tex_error < 3:
300+
context += tex_source[: line_of_tex_error + 3]
301+
context[-4] = "-> " + context[-4]
302+
elif line_of_tex_error > len(tex_source) - 3:
303+
context += tex_source[line_of_tex_error - 1 :]
304+
context[1] = "-> " + context[1]
299305
else:
300-
marker_before_error = max(
301-
idx for idx in env_markers_indices if idx < line_of_tex_error
302-
)
303-
marker_after_error = min(
304-
idx for idx in env_markers_indices if idx > line_of_tex_error
305-
)
306-
context += "".join(tex_source[marker_before_error:marker_after_error])
306+
context += tex_source[line_of_tex_error - 3 : line_of_tex_error + 3]
307+
context[-4] = "-> " + context[-4]
308+
309+
context = "".join(context)
307310
logger.error(context)
308311

309-
for prog, get_insight in LATEX_ERROR_INSIGHTS:
310-
error_end_index = [
311-
idx
312-
for idx, _ in enumerate(tex_compilation_log[error_start_index:])
313-
if _.startswith("l.")
314-
][0]
315-
match = re.search(
316-
prog,
317-
"".join(tex_compilation_log[error_start_index:error_end_index]),
312+
for insights in LATEX_ERROR_INSIGHTS:
313+
prob, get_insight = insights
314+
matching = re.search(
315+
prob,
316+
"".join(tex_compilation_log[error_start_index])[2:],
318317
)
319-
if match is not None:
320-
for insight in get_insight(match):
318+
if matching is not None:
319+
for insight in get_insight(matching):
321320
logger.info(insight)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{"levelname": "INFO", "module": "logger_utils", "message": "Log file will be saved in <>"}
2+
{"levelname": "INFO", "module": "tex_file_writing", "message": "Writing \\frac{1}{0} to <>"}
3+
{"levelname": "ERROR", "module": "tex_file_writing", "message": "LaTeX compilation error: LaTeX Error: File `notapackage.sty' not found.\n"}
4+
{"levelname": "ERROR", "module": "tex_file_writing", "message": "Context of error: \n\\documentclass[preview]{standalone}\n-> \\usepackage{notapackage}\n\\begin{document}\n\n\\begin{center}\n"}
5+
{"levelname": "INFO", "module": "tex_file_writing", "message": "You do not have package notapackage.sty installed."}
6+
{"levelname": "INFO", "module": "tex_file_writing", "message": "Install notapackage.sty it using your LaTeX package manager, or check for typos."}
7+
{"levelname": "ERROR", "module": "tex_file_writing", "message": "LaTeX compilation error: Emergency stop.\n"}
8+
{"levelname": "ERROR", "module": "tex_file_writing", "message": "Context of error: \n\\documentclass[preview]{standalone}\n-> \\usepackage{notapackage}\n\\begin{document}\n\n\\begin{center}\n"}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from manim import Scene, Tex, TexTemplate
2+
3+
4+
class BadTex(Scene):
5+
def construct(self):
6+
tex_template = TexTemplate(preamble=r"\usepackage{notapackage}")
7+
some_tex = r"\frac{1}{0}"
8+
my_tex = Tex(some_tex, tex_template=tex_template)
9+
self.add(my_tex)

tests/test_logging/test_logging.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,26 @@ def test_error_logging(tmp_path, python_version):
7676

7777
_, err, exitcode = capture(command)
7878
assert exitcode != 0 and len(err) > 0
79+
80+
81+
@logs_comparison(
82+
"bad_tex_scene_BadTex.txt",
83+
Path("logs/bad_tex_scene_BadTex.log"),
84+
)
85+
def test_tex_error_logs(tmp_path, python_version):
86+
bad_tex_scene = os.path.join("tests", "test_logging", "bad_tex_scene.py")
87+
command = [
88+
python_version,
89+
"-m",
90+
"manim",
91+
"-ql",
92+
"--log_to_file",
93+
"-v",
94+
"INFO",
95+
"--media_dir",
96+
str(tmp_path),
97+
bad_tex_scene,
98+
"BadTex",
99+
]
100+
_, err, exitcode = capture(command)
101+
assert exitcode != 0 and len(err) > 0

0 commit comments

Comments
 (0)