From 0a96aacb24a7aff71a631cf1915b4b371fe40d9b Mon Sep 17 00:00:00 2001 From: Achille Fouilleul Date: Wed, 16 Oct 2024 01:43:02 +0200 Subject: [PATCH] os.system -> subprocess (#3955) Quoting the python library documentation: > The subprocess module provides more powerful facilities for spawning > new processes and retrieving their results; using that module is > preferable to using this function. --- manim/utils/tex_file_writing.py | 61 +++++++++++++++------------------ scripts/make_and_open_docs.py | 6 ++-- 2 files changed, 31 insertions(+), 36 deletions(-) diff --git a/manim/utils/tex_file_writing.py b/manim/utils/tex_file_writing.py index 777827859e..45e84d4907 100644 --- a/manim/utils/tex_file_writing.py +++ b/manim/utils/tex_file_writing.py @@ -9,8 +9,8 @@ from __future__ import annotations import hashlib -import os import re +import subprocess import unicodedata from collections.abc import Iterable from pathlib import Path @@ -114,10 +114,11 @@ def generate_tex_file( return result -def tex_compilation_command( +def make_tex_compilation_command( tex_compiler: str, output_format: str, tex_file: Path, tex_dir: Path -) -> str: - """Prepares the tex compilation command with all necessary cli flags +) -> list[str]: + """Prepares the TeX compilation command, i.e. the TeX compiler name + and all necessary CLI flags. Parameters ---------- @@ -132,40 +133,36 @@ def tex_compilation_command( Returns ------- - :class:`str` + :class:`list[str]` Compilation command according to given parameters """ if tex_compiler in {"latex", "pdflatex", "luatex", "lualatex"}: - commands = [ + command = [ tex_compiler, "-interaction=batchmode", - f'-output-format="{output_format[1:]}"', + f"-output-format={output_format[1:]}", "-halt-on-error", - f'-output-directory="{tex_dir.as_posix()}"', - f'"{tex_file.as_posix()}"', - ">", - os.devnull, + f"-output-directory={tex_dir.as_posix()}", + f"{tex_file.as_posix()}", ] elif tex_compiler == "xelatex": if output_format == ".xdv": - outflag = "-no-pdf" + outflag = ["-no-pdf"] elif output_format == ".pdf": - outflag = "" + outflag = [] else: raise ValueError("xelatex output is either pdf or xdv") - commands = [ + command = [ "xelatex", - outflag, + *outflag, "-interaction=batchmode", "-halt-on-error", - f'-output-directory="{tex_dir.as_posix()}"', - f'"{tex_file.as_posix()}"', - ">", - os.devnull, + f"-output-directory={tex_dir.as_posix()}", + f"{tex_file.as_posix()}", ] else: raise ValueError(f"Tex compiler {tex_compiler} unknown.") - return " ".join(commands) + return command def insight_inputenc_error(matching): @@ -200,14 +197,14 @@ def compile_tex(tex_file: Path, tex_compiler: str, output_format: str) -> Path: result = tex_file.with_suffix(output_format) tex_dir = config.get_dir("tex_dir") if not result.exists(): - command = tex_compilation_command( + command = make_tex_compilation_command( tex_compiler, output_format, tex_file, tex_dir, ) - exit_code = os.system(command) - if exit_code != 0: + cp = subprocess.run(command, stdout=subprocess.DEVNULL) + if cp.returncode != 0: log_file = tex_file.with_suffix(".log") print_all_tex_errors(log_file, tex_compiler, tex_file) raise ValueError( @@ -237,18 +234,16 @@ def convert_to_svg(dvi_file: Path, extension: str, page: int = 1): """ result = dvi_file.with_suffix(".svg") if not result.exists(): - commands = [ + command = [ "dvisvgm", - "--pdf" if extension == ".pdf" else "", - "-p " + str(page), - f'"{dvi_file.as_posix()}"', - "-n", - "-v 0", - "-o " + f'"{result.as_posix()}"', - ">", - os.devnull, + *(["--pdf"] if extension == ".pdf" else []), + f"--page={page}", + "--no-fonts", + "--verbosity=0", + f"--output={result.as_posix()}", + f"{dvi_file.as_posix()}", ] - os.system(" ".join(commands)) + subprocess.run(command, stdout=subprocess.DEVNULL) # if the file does not exist now, this means conversion failed if not result.exists(): diff --git a/scripts/make_and_open_docs.py b/scripts/make_and_open_docs.py index 11b9360edc..c6179384ba 100644 --- a/scripts/make_and_open_docs.py +++ b/scripts/make_and_open_docs.py @@ -1,12 +1,12 @@ from __future__ import annotations -import os +import subprocess import sys import webbrowser from pathlib import Path -path_makefile = Path(__file__).parents[1] / "docs" -os.system(f"cd {path_makefile} && make html") +path_makefile = Path(__file__).resolve().parents[1] / "docs" +subprocess.run(["make", "html"], cwd=path_makefile) website = (path_makefile / "build" / "html" / "index.html").absolute().as_uri() try: # Allows you to pass a custom browser if you want.