Skip to content

Commit

Permalink
Trac #34282: Make feature TeXFile check latex first
Browse files Browse the repository at this point in the history
Currently, as observed in
[https://trac.sagemath.org/ticket/34185#comment:7 comment 7] of #34185,
the method `is_present` of instances of class `TeXFile` runs into an
exception if latex is not installed. For example:

{{{
sage: from sage.features.latex import LaTeXPackage
sage: LaTeXPackage("tkz-graph").is_present()
Traceback (most recent call last):
...
FileNotFoundError: [Errno 2] No such file or directory: 'kpsewhich'
}}}

The aim of the ticket is to fix this.

URL: https://trac.sagemath.org/34282
Reported by: soehms
Ticket author(s): Sebastian Oehms, Kwankyu Lee
Reviewer(s): Kwankyu Lee, Sebastian Oehms
  • Loading branch information
Release Manager committed Sep 20, 2022
2 parents 5c42b1b + a77ff0c commit 1ec500e
Showing 1 changed file with 68 additions and 23 deletions.
91 changes: 68 additions & 23 deletions src/sage/features/latex.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@

from . import StaticFile, Executable, FeatureTestResult, FeatureNotPresentError

class latex(Executable):
latex_url = 'https://www.latex-project.org/'
latex_spkg = 'texlive'


class LaTeX(Executable):
r"""
A :class:`~sage.features.Feature` describing the presence of ``latex``
Expand All @@ -24,16 +28,15 @@ class latex(Executable):
sage: latex().is_present() # optional - latex
FeatureTestResult('latex', True)
"""
def __init__(self):
def __init__(self, name):
r"""
TESTS::
sage: from sage.features.latex import latex
sage: isinstance(latex(), latex)
True
"""
Executable.__init__(self, "latex", executable="latex",
url="https://www.latex-project.org/")
super().__init__(name, executable=name, spkg=latex_spkg, url=latex_url)

def is_functional(self):
r"""
Expand Down Expand Up @@ -62,7 +65,7 @@ def is_functional(self):

# running latex
from subprocess import run
cmd = ['latex', '-interaction=nonstopmode', filename_tex]
cmd = [self.name, '-interaction=nonstopmode', filename_tex]
cmd = ' '.join(cmd)
result = run(cmd, shell=True, cwd=base, capture_output=True, text=True)

Expand All @@ -71,10 +74,32 @@ def is_functional(self):
return FeatureTestResult(self, True)
else:
return FeatureTestResult(self, False, reason="Running latex on "
"a sample file returned non-zero "
"exit status {}".format(result.returncode))
"a sample file returned non-zero "
"exit status {}".format(result.returncode))


class latex(LaTeX):
r"""
A :class:`~sage.features.Feature` describing the presence of ``latex``
EXAMPLES::
sage: from sage.features.latex import latex
sage: latex().is_present() # optional - latex
FeatureTestResult('latex', True)
"""
def __init__(self):
r"""
TESTS::
sage: from sage.features.latex import latex
sage: isinstance(latex(), latex)
True
"""
super().__init__("latex")

class pdflatex(Executable):

class pdflatex(LaTeX):
r"""
A :class:`~sage.features.Feature` describing the presence of ``pdflatex``
Expand All @@ -92,10 +117,10 @@ def __init__(self):
sage: isinstance(pdflatex(), pdflatex)
True
"""
Executable.__init__(self, "pdflatex", executable="pdflatex",
url="https://www.latex-project.org/")
super().__init__("pdflatex")


class xelatex(Executable):
class xelatex(LaTeX):
r"""
A :class:`~sage.features.Feature` describing the presence of ``xelatex``
Expand All @@ -113,10 +138,10 @@ def __init__(self):
sage: isinstance(xelatex(), xelatex)
True
"""
Executable.__init__(self, "xelatex", executable="xelatex",
url="https://www.latex-project.org/")
super().__init__("xelatex")

class lualatex(Executable):

class lualatex(LaTeX):
r"""
A :class:`~sage.features.Feature` describing the presence of ``lualatex``
Expand All @@ -134,8 +159,7 @@ def __init__(self):
sage: isinstance(lualatex(), lualatex)
True
"""
Executable.__init__(self, "lualatex", executable="lualatex",
url="https://www.latex-project.org/")
super().__init__("lualatex")


class TeXFile(StaticFile):
Expand All @@ -145,12 +169,19 @@ class TeXFile(StaticFile):
EXAMPLES::
sage: from sage.features.latex import TeXFile
sage: TeXFile('x', 'x.tex').is_present() # optional: pdflatex
sage: TeXFile('x', 'x.tex').is_present() # optional - latex
FeatureTestResult('x', True)
sage: TeXFile('nonexisting', 'xxxxxx-nonexisting-file.tex').is_present() # optional - pdflatex
FeatureTestResult('nonexisting', False)
"""
def __init__(self, name, filename, **kwds):
r"""
Initialize.
TESTS::
sage: from sage.features.latex import TeXFile
sage: TeXFile('nonexisting', 'xxxxxx-nonexisting-file.tex').is_present() # optional - latex
FeatureTestResult('nonexisting', False)
"""
StaticFile.__init__(self, name, filename, search_path=[], **kwds)

def absolute_filename(self) -> str:
Expand All @@ -161,7 +192,7 @@ def absolute_filename(self) -> str:
sage: from sage.features.latex import TeXFile
sage: feature = TeXFile('latex_class_article', 'article.cls')
sage: feature.absolute_filename() # optional - pdflatex
sage: feature.absolute_filename() # optional - latex
'.../latex/base/article.cls'
"""
from subprocess import run, CalledProcessError, PIPE
Expand All @@ -171,8 +202,22 @@ def absolute_filename(self) -> str:
universal_newlines=True, check=True)
return proc.stdout.strip()
except CalledProcessError:
raise FeatureNotPresentError(self,
reason="{filename!r} not found by kpsewhich".format(filename=self.filename))
reason = "{filename!r} not found by kpsewhich".format(filename=self.filename)
raise FeatureNotPresentError(self, reason)

def _is_present(self):
r"""
Test for the presence of the TeX file.
EXAMPLES::
sage: from sage.features.latex import LaTeXPackage, latex
sage: f = LaTeXPackage("tkz-graph")
sage: g = latex()
sage: not f.is_present() or bool(g.is_present()) # indirect doctest
True
"""
return latex().is_present() and super()._is_present()


class LaTeXPackage(TeXFile):
Expand All @@ -183,7 +228,7 @@ class LaTeXPackage(TeXFile):
EXAMPLES::
sage: from sage.features.latex import LaTeXPackage
sage: LaTeXPackage('graphics').is_present() # optional - pdflatex
sage: LaTeXPackage('graphics').is_present() # optional - latex
FeatureTestResult('latex_package_graphics', True)
"""
@staticmethod
Expand Down

0 comments on commit 1ec500e

Please sign in to comment.