mirror of
https://github.com/ManimCommunity/manim.git
synced 2026-06-22 10:01:47 +00:00
Merge branch 'main' into guide
This commit is contained in:
commit
0a9d095372
7 changed files with 267 additions and 217 deletions
|
|
@ -36,6 +36,8 @@ logging.getLogger("PIL").setLevel(logging.INFO)
|
|||
logging.getLogger("matplotlib").setLevel(logging.INFO)
|
||||
|
||||
config = ManimConfig().digest_parser(parser)
|
||||
# TODO: to be used in the future - see PR #620
|
||||
# https://github.com/ManimCommunity/manim/pull/620
|
||||
frame = ManimFrame(config)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ import numpy as np
|
|||
from manim import constants
|
||||
from manim.constants import RendererType
|
||||
from manim.utils.color import ManimColor
|
||||
from manim.utils.tex import TexTemplate, TexTemplateFromFile
|
||||
from manim.utils.tex import TexTemplate
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from enum import EnumMeta
|
||||
|
|
@ -833,7 +833,7 @@ class ManimConfig(MutableMapping):
|
|||
|
||||
# Handle --tex_template
|
||||
if args.tex_template:
|
||||
self.tex_template = TexTemplateFromFile(tex_filename=args.tex_template)
|
||||
self.tex_template = TexTemplate.from_file(args.tex_template)
|
||||
|
||||
if (
|
||||
self.renderer == RendererType.OPENGL
|
||||
|
|
@ -1756,19 +1756,19 @@ class ManimConfig(MutableMapping):
|
|||
if not hasattr(self, "_tex_template") or not self._tex_template:
|
||||
fn = self._d["tex_template_file"]
|
||||
if fn:
|
||||
self._tex_template = TexTemplateFromFile(tex_filename=fn)
|
||||
self._tex_template = TexTemplate.from_file(fn)
|
||||
else:
|
||||
self._tex_template = TexTemplate()
|
||||
return self._tex_template
|
||||
|
||||
@tex_template.setter
|
||||
def tex_template(self, val: TexTemplateFromFile | TexTemplate) -> None:
|
||||
if isinstance(val, (TexTemplateFromFile, TexTemplate)):
|
||||
def tex_template(self, val: TexTemplate) -> None:
|
||||
if isinstance(val, TexTemplate):
|
||||
self._tex_template = val
|
||||
|
||||
@property
|
||||
def tex_template_file(self) -> Path:
|
||||
"""File to read Tex template from (no flag). See :class:`.TexTemplateFromFile`."""
|
||||
"""File to read Tex template from (no flag). See :class:`.TexTemplate`."""
|
||||
return self._d["tex_template_file"]
|
||||
|
||||
@tex_template_file.setter
|
||||
|
|
@ -1793,6 +1793,8 @@ class ManimConfig(MutableMapping):
|
|||
self._d["plugins"] = value
|
||||
|
||||
|
||||
# TODO: to be used in the future - see PR #620
|
||||
# https://github.com/ManimCommunity/manim/pull/620
|
||||
class ManimFrame(Mapping):
|
||||
_OPTS: ClassVar[set[str]] = {
|
||||
"pixel_width",
|
||||
|
|
|
|||
|
|
@ -4,162 +4,132 @@ from __future__ import annotations
|
|||
|
||||
__all__ = [
|
||||
"TexTemplate",
|
||||
"TexTemplateFromFile",
|
||||
]
|
||||
|
||||
import copy
|
||||
import os
|
||||
import re
|
||||
import warnings
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing_extensions import Self
|
||||
|
||||
class TexTemplate:
|
||||
"""TeX templates are used for creating Tex() and MathTex() objects.
|
||||
from manim.typing import StrPath
|
||||
|
||||
Parameters
|
||||
----------
|
||||
tex_compiler
|
||||
The TeX compiler to be used, e.g. ``latex``, ``pdflatex`` or ``lualatex``
|
||||
output_format
|
||||
The output format resulting from compilation, e.g. ``.dvi`` or ``.pdf``
|
||||
documentclass
|
||||
The command defining the documentclass, e.g. ``\\documentclass[preview]{standalone}``
|
||||
preamble
|
||||
The document's preamble, i.e. the part between ``\\documentclass`` and ``\\begin{document}``
|
||||
placeholder_text
|
||||
Text in the document that will be replaced by the expression to be rendered
|
||||
post_doc_commands
|
||||
Text (definitions, commands) to be inserted at right after ``\\begin{document}``, e.g. ``\\boldmath``
|
||||
|
||||
Attributes
|
||||
----------
|
||||
tex_compiler : :class:`str`
|
||||
The TeX compiler to be used, e.g. ``latex``, ``pdflatex`` or ``lualatex``
|
||||
output_format : :class:`str`
|
||||
The output format resulting from compilation, e.g. ``.dvi`` or ``.pdf``
|
||||
documentclass : :class:`str`
|
||||
The command defining the documentclass, e.g. ``\\documentclass[preview]{standalone}``
|
||||
preamble : :class:`str`
|
||||
The document's preamble, i.e. the part between ``\\documentclass`` and ``\\begin{document}``
|
||||
placeholder_text : :class:`str`
|
||||
Text in the document that will be replaced by the expression to be rendered
|
||||
post_doc_commands : :class:`str`
|
||||
Text (definitions, commands) to be inserted at right after ``\\begin{document}``, e.g. ``\\boldmath``
|
||||
"""
|
||||
|
||||
default_documentclass = r"\documentclass[preview]{standalone}"
|
||||
default_preamble = r"""
|
||||
\usepackage[english]{babel}
|
||||
_DEFAULT_PREAMBLE = r"""\usepackage[english]{babel}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amssymb}
|
||||
"""
|
||||
default_placeholder_text = "YourTextHere"
|
||||
default_tex_compiler = "latex"
|
||||
default_output_format = ".dvi"
|
||||
default_post_doc_commands = ""
|
||||
\usepackage{amssymb}"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
tex_compiler: str | None = None,
|
||||
output_format: str | None = None,
|
||||
documentclass: str | None = None,
|
||||
preamble: str | None = None,
|
||||
placeholder_text: str | None = None,
|
||||
post_doc_commands: str | None = None,
|
||||
**kwargs,
|
||||
):
|
||||
self.tex_compiler = (
|
||||
tex_compiler
|
||||
if tex_compiler is not None
|
||||
else TexTemplate.default_tex_compiler
|
||||
)
|
||||
self.output_format = (
|
||||
output_format
|
||||
if output_format is not None
|
||||
else TexTemplate.default_output_format
|
||||
)
|
||||
self.documentclass = (
|
||||
documentclass
|
||||
if documentclass is not None
|
||||
else TexTemplate.default_documentclass
|
||||
)
|
||||
self.preamble = (
|
||||
preamble if preamble is not None else TexTemplate.default_preamble
|
||||
)
|
||||
self.placeholder_text = (
|
||||
placeholder_text
|
||||
if placeholder_text is not None
|
||||
else TexTemplate.default_placeholder_text
|
||||
)
|
||||
self.post_doc_commands = (
|
||||
post_doc_commands
|
||||
if post_doc_commands is not None
|
||||
else TexTemplate.default_post_doc_commands
|
||||
)
|
||||
self._rebuild()
|
||||
_BEGIN_DOCUMENT = r"\begin{document}"
|
||||
_END_DOCUMENT = r"\end{document}"
|
||||
|
||||
def __eq__(self, other: TexTemplate) -> bool:
|
||||
return (
|
||||
self.body == other.body
|
||||
and self.tex_compiler == other.tex_compiler
|
||||
and self.output_format == other.output_format
|
||||
and self.post_doc_commands == other.post_doc_commands
|
||||
|
||||
@dataclass(eq=True)
|
||||
class TexTemplate:
|
||||
"""TeX templates are used to create ``Tex`` and ``MathTex`` objects."""
|
||||
|
||||
_body: str = field(default="", init=False)
|
||||
"""A custom body, can be set from a file."""
|
||||
|
||||
tex_compiler: str = "latex"
|
||||
"""The TeX compiler to be used, e.g. ``latex``, ``pdflatex`` or ``lualatex``."""
|
||||
|
||||
output_format: str = ".dvi"
|
||||
"""The output format resulting from compilation, e.g. ``.dvi`` or ``.pdf``."""
|
||||
|
||||
documentclass: str = r"\documentclass[preview]{standalone}"
|
||||
r"""The command defining the documentclass, e.g. ``\documentclass[preview]{standalone}``."""
|
||||
|
||||
preamble: str = _DEFAULT_PREAMBLE
|
||||
r"""The document's preamble, i.e. the part between ``\documentclass`` and ``\begin{document}``."""
|
||||
|
||||
placeholder_text: str = "YourTextHere"
|
||||
"""Text in the document that will be replaced by the expression to be rendered."""
|
||||
|
||||
post_doc_commands: str = ""
|
||||
r"""Text (definitions, commands) to be inserted at right after ``\begin{document}``, e.g. ``\boldmath``."""
|
||||
|
||||
@property
|
||||
def body(self) -> str:
|
||||
"""The entire TeX template."""
|
||||
return self._body or "\n".join(
|
||||
filter(
|
||||
None,
|
||||
[
|
||||
self.documentclass,
|
||||
self.preamble,
|
||||
_BEGIN_DOCUMENT,
|
||||
self.post_doc_commands,
|
||||
self.placeholder_text,
|
||||
_END_DOCUMENT,
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
def _rebuild(self):
|
||||
"""Rebuilds the entire TeX template text from ``\\documentclass`` to ``\\end{document}`` according to all settings and choices."""
|
||||
self.body = (
|
||||
self.documentclass
|
||||
+ "\n"
|
||||
+ self.preamble
|
||||
+ "\n"
|
||||
+ r"\begin{document}"
|
||||
+ "\n"
|
||||
+ self.post_doc_commands
|
||||
+ "\n"
|
||||
+ self.placeholder_text
|
||||
+ "\n"
|
||||
+ "\n"
|
||||
+ r"\end{document}"
|
||||
+ "\n"
|
||||
)
|
||||
@body.setter
|
||||
def body(self, value: str) -> None:
|
||||
self._body = value
|
||||
|
||||
def add_to_preamble(self, txt: str, prepend: bool = False):
|
||||
"""Adds stuff to the TeX template's preamble (e.g. definitions, packages). Text can be inserted at the beginning or at the end of the preamble.
|
||||
@classmethod
|
||||
def from_file(cls, file: StrPath = "tex_template.tex", **kwargs: Any) -> Self:
|
||||
"""Create an instance by reading the content of a file.
|
||||
|
||||
Using the ``add_to_preamble`` and ``add_to_document`` methods on this instance
|
||||
will have no effect, as the body is read from the file.
|
||||
"""
|
||||
instance = cls(**kwargs)
|
||||
instance.body = Path(file).read_text(encoding="utf-8")
|
||||
return instance
|
||||
|
||||
def add_to_preamble(self, txt: str, prepend: bool = False) -> Self:
|
||||
r"""Adds text to the TeX template's preamble (e.g. definitions, packages). Text can be inserted at the beginning or at the end of the preamble.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
txt
|
||||
String containing the text to be added, e.g. ``\\usepackage{hyperref}``
|
||||
String containing the text to be added, e.g. ``\usepackage{hyperref}``.
|
||||
prepend
|
||||
Whether the text should be added at the beginning of the preamble, i.e. right after ``\\documentclass``. Default is to add it at the end of the preamble, i.e. right before ``\\begin{document}``
|
||||
Whether the text should be added at the beginning of the preamble, i.e. right after ``\documentclass``.
|
||||
Default is to add it at the end of the preamble, i.e. right before ``\begin{document}``.
|
||||
"""
|
||||
if self._body:
|
||||
warnings.warn(
|
||||
"This TeX template was created with a fixed body, trying to add text the preamble will have no effect.",
|
||||
UserWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
if prepend:
|
||||
self.preamble = txt + "\n" + self.preamble
|
||||
else:
|
||||
self.preamble += "\n" + txt
|
||||
self._rebuild()
|
||||
return self
|
||||
|
||||
def add_to_document(self, txt: str):
|
||||
"""Adds txt to the TeX template just after \\begin{document}, e.g. ``\\boldmath``
|
||||
def add_to_document(self, txt: str) -> Self:
|
||||
r"""Adds text to the TeX template just after \begin{document}, e.g. ``\boldmath``.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
txt
|
||||
String containing the text to be added.
|
||||
"""
|
||||
self.post_doc_commands += "\n" + txt + "\n"
|
||||
self._rebuild()
|
||||
if self._body:
|
||||
warnings.warn(
|
||||
"This TeX template was created with a fixed body, trying to add text the document will have no effect.",
|
||||
UserWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
self.post_doc_commands += txt
|
||||
return self
|
||||
|
||||
def get_texcode_for_expression(self, expression: str):
|
||||
"""Inserts expression verbatim into TeX template.
|
||||
def get_texcode_for_expression(self, expression: str) -> str:
|
||||
r"""Inserts expression verbatim into TeX template.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
expression
|
||||
The string containing the expression to be typeset, e.g. ``$\\sqrt{2}$``
|
||||
The string containing the expression to be typeset, e.g. ``$\sqrt{2}$``
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
|
@ -168,102 +138,60 @@ class TexTemplate:
|
|||
"""
|
||||
return self.body.replace(self.placeholder_text, expression)
|
||||
|
||||
def _texcode_for_environment(self, environment: str):
|
||||
"""Processes the tex_environment string to return the correct ``\\begin{environment}[extra]{extra}`` and
|
||||
``\\end{environment}`` strings
|
||||
|
||||
Parameters
|
||||
----------
|
||||
environment
|
||||
The tex_environment as a string. Acceptable formats include:
|
||||
``{align*}``, ``align*``, ``{tabular}[t]{cccl}``, ``tabular}{cccl``, ``\\begin{tabular}[t]{cccl}``.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Tuple[:class:`str`, :class:`str`]
|
||||
A pair of strings representing the opening and closing of the tex environment, e.g.
|
||||
``\\begin{tabular}{cccl}`` and ``\\end{tabular}``
|
||||
"""
|
||||
|
||||
# If the environment starts with \begin, remove it
|
||||
if environment[0:6] == r"\begin":
|
||||
environment = environment[6:]
|
||||
|
||||
# If environment begins with { strip it
|
||||
if environment[0] == r"{":
|
||||
environment = environment[1:]
|
||||
|
||||
# The \begin command takes everything and closes with a brace
|
||||
begin = r"\begin{" + environment
|
||||
if (
|
||||
begin[-1] != r"}" and begin[-1] != r"]"
|
||||
): # If it doesn't end on } or ], assume missing }
|
||||
begin += r"}"
|
||||
|
||||
# While the \end command terminates at the first closing brace
|
||||
split_at_brace = re.split(r"}", environment, 1)
|
||||
end = r"\end{" + split_at_brace[0] + r"}"
|
||||
|
||||
return begin, end
|
||||
|
||||
def get_texcode_for_expression_in_env(self, expression: str, environment: str):
|
||||
r"""Inserts expression into TeX template wrapped in \begin{environment} and \end{environment}
|
||||
def get_texcode_for_expression_in_env(
|
||||
self, expression: str, environment: str
|
||||
) -> str:
|
||||
r"""Inserts expression into TeX template wrapped in ``\begin{environment}`` and ``\end{environment}``.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
expression
|
||||
The string containing the expression to be typeset, e.g. ``$\\sqrt{2}$``
|
||||
The string containing the expression to be typeset, e.g. ``$\sqrt{2}$``.
|
||||
environment
|
||||
The string containing the environment in which the expression should be typeset, e.g. ``align*``
|
||||
The string containing the environment in which the expression should be typeset, e.g. ``align*``.
|
||||
|
||||
Returns
|
||||
-------
|
||||
:class:`str`
|
||||
LaTeX code based on template, containing the given expression inside its environment, ready for typesetting
|
||||
"""
|
||||
begin, end = self._texcode_for_environment(environment)
|
||||
return self.body.replace(self.placeholder_text, f"{begin}\n{expression}\n{end}")
|
||||
begin, end = _texcode_for_environment(environment)
|
||||
return self.body.replace(
|
||||
self.placeholder_text, "\n".join([begin, expression, end])
|
||||
)
|
||||
|
||||
def copy(self) -> TexTemplate:
|
||||
def copy(self) -> Self:
|
||||
"""Create a deep copy of the TeX template instance."""
|
||||
return copy.deepcopy(self)
|
||||
|
||||
|
||||
class TexTemplateFromFile(TexTemplate):
|
||||
"""A TexTemplate object created from a template file (default: tex_template.tex)
|
||||
def _texcode_for_environment(environment: str) -> tuple[str, str]:
|
||||
r"""Processes the tex_environment string to return the correct ``\begin{environment}[extra]{extra}`` and
|
||||
``\end{environment}`` strings.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
tex_filename
|
||||
Path to a valid TeX template file
|
||||
kwargs
|
||||
Arguments for :class:`~.TexTemplate`.
|
||||
environment
|
||||
The tex_environment as a string. Acceptable formats include:
|
||||
``{align*}``, ``align*``, ``{tabular}[t]{cccl}``, ``tabular}{cccl``, ``\begin{tabular}[t]{cccl}``.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
template_file : :class:`str`
|
||||
Path to a valid TeX template file
|
||||
body : :class:`str`
|
||||
Content of the TeX template file
|
||||
tex_compiler : :class:`str`
|
||||
The TeX compiler to be used, e.g. ``latex``, ``pdflatex`` or ``lualatex``
|
||||
output_format : :class:`str`
|
||||
The output format resulting from compilation, e.g. ``.dvi`` or ``.pdf``
|
||||
Returns
|
||||
-------
|
||||
Tuple[:class:`str`, :class:`str`]
|
||||
A pair of strings representing the opening and closing of the tex environment, e.g.
|
||||
``\begin{tabular}{cccl}`` and ``\end{tabular}``
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, *, tex_filename: str | os.PathLike = "tex_template.tex", **kwargs
|
||||
):
|
||||
self.template_file = Path(tex_filename)
|
||||
super().__init__(**kwargs)
|
||||
environment.removeprefix(r"\begin").removeprefix("{")
|
||||
|
||||
def _rebuild(self):
|
||||
self.body = self.template_file.read_text()
|
||||
# The \begin command takes everything and closes with a brace
|
||||
begin = r"\begin{" + environment
|
||||
# If it doesn't end on } or ], assume missing }
|
||||
if not begin.endswith(("}", "]")):
|
||||
begin += "}"
|
||||
|
||||
def file_not_mutable(self):
|
||||
raise Exception("Cannot modify TexTemplate when using a template file.")
|
||||
# While the \end command terminates at the first closing brace
|
||||
split_at_brace = re.split("}", environment, 1)
|
||||
end = r"\end{" + split_at_brace[0] + "}"
|
||||
|
||||
def add_to_preamble(self, txt, prepend=False):
|
||||
self.file_not_mutable()
|
||||
|
||||
def add_to_document(self, txt):
|
||||
self.file_not_mutable()
|
||||
return begin, end
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
{"levelname": "INFO", "module": "logger_utils", "message": "Log file will be saved in <>"}
|
||||
{"levelname": "INFO", "module": "tex_file_writing", "message": "Writing <> to <>"}
|
||||
{"levelname": "ERROR", "module": "tex_file_writing", "message": "LaTeX compilation error: LaTeX Error: File `notapackage.sty' not found.\n"}
|
||||
{"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"}
|
||||
{"levelname": "ERROR", "module": "tex_file_writing", "message": "Context of error: \n\\documentclass[preview]{standalone}\n-> \\usepackage{notapackage}\n\\begin{document}\n\\begin{center}\n\\frac{1}{0}\n"}
|
||||
{"levelname": "INFO", "module": "tex_file_writing", "message": "You do not have package notapackage.sty installed."}
|
||||
{"levelname": "INFO", "module": "tex_file_writing", "message": "Install notapackage.sty it using your LaTeX package manager, or check for typos."}
|
||||
{"levelname": "ERROR", "module": "tex_file_writing", "message": "LaTeX compilation error: Emergency stop.\n"}
|
||||
{"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"}
|
||||
{"levelname": "ERROR", "module": "tex_file_writing", "message": "Context of error: \n\\documentclass[preview]{standalone}\n-> \\usepackage{notapackage}\n\\begin{document}\n\\begin{center}\n\\frac{1}{0}\n"}
|
||||
|
|
|
|||
|
|
@ -12,12 +12,12 @@ from manim.utils.color import RED
|
|||
|
||||
def test_MathTex():
|
||||
MathTex("a^2 + b^2 = c^2")
|
||||
assert Path(config.media_dir, "Tex", "eb38bdba08f46c80.svg").exists()
|
||||
assert Path(config.media_dir, "Tex", "e4be163a00cf424f.svg").exists()
|
||||
|
||||
|
||||
def test_SingleStringMathTex():
|
||||
SingleStringMathTex("test")
|
||||
assert Path(config.media_dir, "Tex", "5b2faa68ebf42d1e.svg").exists()
|
||||
assert Path(config.media_dir, "Tex", "8ce17c7f5013209f.svg").exists()
|
||||
|
||||
|
||||
@pytest.mark.parametrize( # : PT006
|
||||
|
|
@ -31,7 +31,7 @@ def test_double_braces_testing(text_input, length_sub):
|
|||
|
||||
def test_tex():
|
||||
Tex("The horse does not eat cucumber salad.")
|
||||
assert Path(config.media_dir, "Tex", "f2e45e6e82d750e6.svg").exists()
|
||||
assert Path(config.media_dir, "Tex", "c3945e23e546c95a.svg").exists()
|
||||
|
||||
|
||||
def test_tex_temp_directory(tmpdir, monkeypatch):
|
||||
|
|
@ -44,12 +44,12 @@ def test_tex_temp_directory(tmpdir, monkeypatch):
|
|||
with tempconfig({"media_dir": "media"}):
|
||||
Tex("The horse does not eat cucumber salad.")
|
||||
assert Path("media", "Tex").exists()
|
||||
assert Path("media", "Tex", "f2e45e6e82d750e6.svg").exists()
|
||||
assert Path("media", "Tex", "c3945e23e546c95a.svg").exists()
|
||||
|
||||
|
||||
def test_percent_char_rendering():
|
||||
Tex(r"\%")
|
||||
assert Path(config.media_dir, "Tex", "3f48edf8ebaf82c8.tex").exists()
|
||||
assert Path(config.media_dir, "Tex", "4a583af4d19a3adf.tex").exists()
|
||||
|
||||
|
||||
def test_tex_whitespace_arg():
|
||||
|
|
@ -219,10 +219,10 @@ def test_tex_garbage_collection(tmpdir, monkeypatch):
|
|||
Path(tmpdir, "media").mkdir()
|
||||
|
||||
with tempconfig({"media_dir": "media"}):
|
||||
tex_without_log = Tex("Hello World!") # f7bc61042256dea9.tex
|
||||
assert Path("media", "Tex", "f7bc61042256dea9.tex").exists()
|
||||
assert not Path("media", "Tex", "f7bc61042256dea9.log").exists()
|
||||
tex_without_log = Tex("Hello World!") # d771330b76d29ffb.tex
|
||||
assert Path("media", "Tex", "d771330b76d29ffb.tex").exists()
|
||||
assert not Path("media", "Tex", "d771330b76d29ffb.log").exists()
|
||||
|
||||
with tempconfig({"media_dir": "media", "no_latex_cleanup": True}):
|
||||
tex_with_log = Tex("Hello World, again!") # 3ef79eaaa2d0b15b.tex
|
||||
assert Path("media", "Tex", "3ef79eaaa2d0b15b.log").exists()
|
||||
tex_with_log = Tex("Hello World, again!") # da27670a37b08799.tex
|
||||
assert Path("media", "Tex", "da27670a37b08799.log").exists()
|
||||
|
|
|
|||
118
tests/module/utils/test_tex.py
Normal file
118
tests/module/utils/test_tex.py
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
import pytest
|
||||
|
||||
from manim.utils.tex import TexTemplate
|
||||
|
||||
DEFAULT_BODY = r"""\documentclass[preview]{standalone}
|
||||
\usepackage[english]{babel}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amssymb}
|
||||
\begin{document}
|
||||
YourTextHere
|
||||
\end{document}"""
|
||||
|
||||
BODY_WITH_ADDED_PREAMBLE = r"""\documentclass[preview]{standalone}
|
||||
\usepackage[english]{babel}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amssymb}
|
||||
\usepackage{testpackage}
|
||||
\begin{document}
|
||||
YourTextHere
|
||||
\end{document}"""
|
||||
|
||||
BODY_WITH_PREPENDED_PREAMBLE = r"""\documentclass[preview]{standalone}
|
||||
\usepackage{testpackage}
|
||||
\usepackage[english]{babel}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amssymb}
|
||||
\begin{document}
|
||||
YourTextHere
|
||||
\end{document}"""
|
||||
|
||||
BODY_WITH_ADDED_DOCUMENT = r"""\documentclass[preview]{standalone}
|
||||
\usepackage[english]{babel}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amssymb}
|
||||
\begin{document}
|
||||
\boldmath
|
||||
YourTextHere
|
||||
\end{document}"""
|
||||
|
||||
BODY_REPLACE = r"""\documentclass[preview]{standalone}
|
||||
\usepackage[english]{babel}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amssymb}
|
||||
\begin{document}
|
||||
\sqrt{2}
|
||||
\end{document}"""
|
||||
|
||||
BODY_REPLACE_IN_ENV = r"""\documentclass[preview]{standalone}
|
||||
\usepackage[english]{babel}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{amssymb}
|
||||
\begin{document}
|
||||
\begin{align}
|
||||
\sqrt{2}
|
||||
\end{align}
|
||||
\end{document}"""
|
||||
|
||||
|
||||
def test_tex_template_default_body():
|
||||
template = TexTemplate()
|
||||
assert template.body == DEFAULT_BODY
|
||||
|
||||
|
||||
def test_tex_template_preamble():
|
||||
template = TexTemplate()
|
||||
|
||||
template.add_to_preamble(r"\usepackage{testpackage}")
|
||||
assert template.body == BODY_WITH_ADDED_PREAMBLE
|
||||
|
||||
|
||||
def test_tex_template_preprend_preamble():
|
||||
template = TexTemplate()
|
||||
|
||||
template.add_to_preamble(r"\usepackage{testpackage}", prepend=True)
|
||||
assert template.body == BODY_WITH_PREPENDED_PREAMBLE
|
||||
|
||||
|
||||
def test_tex_template_document():
|
||||
template = TexTemplate()
|
||||
|
||||
template.add_to_document(r"\boldmath")
|
||||
assert template.body == BODY_WITH_ADDED_DOCUMENT
|
||||
|
||||
|
||||
def test_tex_template_texcode_for_expression():
|
||||
template = TexTemplate()
|
||||
|
||||
assert template.get_texcode_for_expression(r"\sqrt{2}") == BODY_REPLACE
|
||||
|
||||
|
||||
def test_tex_template_texcode_for_expression_in_env():
|
||||
template = TexTemplate()
|
||||
|
||||
assert (
|
||||
template.get_texcode_for_expression_in_env(r"\sqrt{2}", environment="align")
|
||||
== BODY_REPLACE_IN_ENV
|
||||
)
|
||||
|
||||
|
||||
def test_tex_template_fixed_body():
|
||||
template = TexTemplate()
|
||||
|
||||
# Usually set when calling `from_file`
|
||||
template.body = "dummy"
|
||||
|
||||
assert template.body == "dummy"
|
||||
|
||||
with pytest.warns(
|
||||
UserWarning,
|
||||
match="This TeX template was created with a fixed body, trying to add text the preamble will have no effect.",
|
||||
):
|
||||
template.add_to_preamble("dummys")
|
||||
|
||||
with pytest.warns(
|
||||
UserWarning,
|
||||
match="This TeX template was created with a fixed body, trying to add text the document will have no effect.",
|
||||
):
|
||||
template.add_to_document("dummy")
|
||||
|
|
@ -9,12 +9,12 @@ from manim import MathTex, SingleStringMathTex, Tex, config
|
|||
|
||||
def test_MathTex(using_opengl_renderer):
|
||||
MathTex("a^2 + b^2 = c^2")
|
||||
assert Path(config.media_dir, "Tex", "eb38bdba08f46c80.svg").exists()
|
||||
assert Path(config.media_dir, "Tex", "e4be163a00cf424f.svg").exists()
|
||||
|
||||
|
||||
def test_SingleStringMathTex(using_opengl_renderer):
|
||||
SingleStringMathTex("test")
|
||||
assert Path(config.media_dir, "Tex", "5b2faa68ebf42d1e.svg").exists()
|
||||
assert Path(config.media_dir, "Tex", "8ce17c7f5013209f.svg").exists()
|
||||
|
||||
|
||||
@pytest.mark.parametrize( # : PT006
|
||||
|
|
@ -28,7 +28,7 @@ def test_double_braces_testing(using_opengl_renderer, text_input, length_sub):
|
|||
|
||||
def test_tex(using_opengl_renderer):
|
||||
Tex("The horse does not eat cucumber salad.")
|
||||
assert Path(config.media_dir, "Tex", "f2e45e6e82d750e6.svg").exists()
|
||||
assert Path(config.media_dir, "Tex", "c3945e23e546c95a.svg").exists()
|
||||
|
||||
|
||||
def test_tex_whitespace_arg(using_opengl_renderer):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue