diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b34bfaa4..f5d0276f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,6 +41,25 @@ jobs: - name: Lint run: | flake8 -v + - name: Install apt deps with cache + uses: awalsh128/cache-apt-pkgs-action@latest + if: "matrix.python-version == '3.11'" + with: + packages: diff-pdf + version: 1.0 + - uses: actions/cache@v3 + name: Tectonic Cache + if: "matrix.python-version == '3.11'" + with: + path: ~/.cache/Tectonic + key: ${{ runner.os }}-tectonic-${{ hashFiles('**/*.tex') }} + restore-keys: | + ${{ runner.os }}-tectonic- + - uses: wtfjoke/setup-tectonic@v2 + if: "matrix.python-version == '3.11'" + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + biber-version: "latest" - name: Test run: | PYTEST_ARGS=(); diff --git a/.gitignore b/.gitignore index 9b724e36..172a254a 100644 --- a/.gitignore +++ b/.gitignore @@ -139,3 +139,6 @@ examples/**/*.tex # Mac .DS_Store + +test/generated +test/diff diff --git a/galgebra/gprinter.py b/galgebra/gprinter.py index 6c76477d..b65a9bcf 100644 --- a/galgebra/gprinter.py +++ b/galgebra/gprinter.py @@ -26,7 +26,7 @@ class LaTeX: latex_preamble = """ \\pagestyle{empty} -\\usepackage[latin1]{inputenc} +\\usepackage[utf8]{inputenc} \\usepackage{amsmath} \\usepackage{amsfonts} \\usepackage{amssymb} @@ -196,7 +196,7 @@ def gprint(*xargs): return -def gxpdf(filename=None, paper=(14, 11), crop=False, png=False, prog=False, debug=False, pt='10pt', pdfprog='pdflatex'): +def gxpdf(filename=None, paper=(14, 11), crop=False, png=False, prog=False, debug=False, pt='10pt', pdfprog='pdflatex', evince=True, rm=True, null=True): """ Post processes LaTeX output (see comments below), adds preamble and @@ -208,10 +208,11 @@ def gxpdf(filename=None, paper=(14, 11), crop=False, png=False, prog=False, debu crop True Use "pdfcrop" to crop output file (pdfcrop must be installed, linux only) png True Use "convert" to produce png output (imagemagick must be installed, linux only) - We assume that if xpdf() is called then Format() has been called at the beginning of the program. + We assume that if gxpdf() is called then gFormat() has been called at the beginning of the program. """ latex_str = paper_format(paper, pt)+LaTeX.latex_preamble+LaTeX.latex_str+r'\end{document}' + if filename is None: pyfilename = sys.argv[0] @@ -221,13 +222,13 @@ def gxpdf(filename=None, paper=(14, 11), crop=False, png=False, prog=False, debu else: tex_filename = filename pdf_filename = tex_filename.replace('.tex', '.pdf') + rootfilename = tex_filename.replace('.tex', '') if debug: print('latex file =', filename) - latex_file = open(tex_filename, 'w') - latex_file.write(latex_str) - latex_file.close() + with open(tex_filename, 'w') as latex_file: + latex_file.write(latex_str) if pdfprog is not None: sys_cmd = SYS_CMD[sys.platform] @@ -237,17 +238,22 @@ def gxpdf(filename=None, paper=(14, 11), crop=False, png=False, prog=False, debu print('pdflatex path =', pdflatex) # os.system(pdfprog + ' ' + filename[:-4]) else: # Works for Linux don't know about Windows - subprocess.call([pdfprog, tex_filename, sys_cmd['null']]) + if null: + subprocess.call([pdfprog, tex_filename, sys_cmd['null']]) + else: + subprocess.call([pdfprog, tex_filename]) # os.system(pdfprog + ' ' + filename[:-4] + sys_cmd['null']) - subprocess.call([sys_cmd['evince'], pdf_filename]) + if evince: + subprocess.call([sys_cmd['evince'], pdf_filename]) # eval(input('!!!!Return to continue!!!!\n')) - if debug: - subprocess.call([sys_cmd['rm'], rootfilename+'.aux ', rootfilename+'.log']) - else: - subprocess.call([sys_cmd['rm'], rootfilename+'.aux ', rootfilename+'.log ', rootfilename+'.tex']) + if rm: + if debug: + subprocess.call([sys_cmd['rm'], rootfilename+'.aux ', rootfilename+'.log']) + else: + subprocess.call([sys_cmd['rm'], rootfilename+'.aux ', rootfilename+'.log ', rootfilename+'.tex']) if crop: subprocess.call(['pdfcrop', pdf_filename]) subprocess.call(['rm', pdf_filename]) diff --git a/test/fixtures/test_gprinter.pdf b/test/fixtures/test_gprinter.pdf new file mode 100644 index 00000000..203f96ae Binary files /dev/null and b/test/fixtures/test_gprinter.pdf differ diff --git a/test/test_gprinter.py b/test/test_gprinter.py new file mode 100644 index 00000000..6e30a755 --- /dev/null +++ b/test/test_gprinter.py @@ -0,0 +1,73 @@ +from __future__ import annotations + +import os +import unittest +import pytest +import subprocess +from pathlib import Path + +# Make SymPy available to this program: +import sympy +from sympy import symbols + +# Make GAlgebra available to this program: +from galgebra.ga import Ga +# from galgebra.mv import * +from galgebra.printer import Fmt, GaPrinter, Format +# Fmt: sets the way that a multivector's basis expansion is output. +# GaPrinter: makes GA output a little more readable. +# Format: turns on latex printer. +from galgebra.gprinter import gFormat, gprint, gxpdf + +ROOT = Path(__file__).parent.parent +DIR_TEST = ROOT / 'test' +DIR_GENERATED = DIR_TEST / 'generated' +DIR_FIXTURES = DIR_TEST / 'fixtures' +DIR_DIFF = DIR_TEST / 'diff' + + +class TestGprinter(unittest.TestCase): + # @pytest.mark.skipif("TEST_GXPDF" not in os.environ, reason="Only run if TEST_GXPDF is set") + def test_gxpdf(self): + gFormat() + # Set up standard G^3 geometric algebra + g3coords = (x, y, z) = symbols('x y z', real=True) # Without real=True, symbols are complex + g3 = Ga(r'\mathbf{e}', g=[1, 1, 1], coords=g3coords) + (ex, ey, ez) = g3.mv() # Program names of basis vectors. + (exr, eyr, ezr) = g3.mvr() # Program names of reciprocal basis vectors. + + B = g3.mv('B', 'bivector') + Fmt(1) # Set Fmt globally + gprint(r'\mathbf{B} =', B) # B will be bold. + gprint(r'\mathbf{B} =', B.Fmt(3)) # Fmt(3) here only. + gprint(r'\mathbf{B} =', B) # Global Fmt remembered. + + gprint(r'\mathbf{B}^2 =', B*B) + + M = g3.mv('M', 'mv') + gprint(r'\langle \mathbf{M} \rangle_2 =', M.grade(2)) + # grade(2) could be replaced by, e.g., odd(), or omitted altogether. + + gprint(r'\alpha_1\mathbf{X}/\gamma_r^3') + + grad = g3.grad + + gprint(r'{\nabla} = ', grad) + + # mkdir -p + os.makedirs(DIR_GENERATED, exist_ok=True) + os.makedirs(DIR_DIFF, exist_ok=True) + os.chdir(DIR_GENERATED) + + gxpdf('test_gprinter.tex', pdfprog='tectonic', rm=False, null=False, evince=False) + + os.chdir(ROOT) + retcode = subprocess.call([ + 'diff-pdf', + '--output-diff=%s' % (DIR_DIFF / 'test_gprinter-diff.pdf'), + DIR_FIXTURES / 'test_gprinter.pdf', + DIR_GENERATED / 'test_gprinter.pdf' + ]) + assert retcode == 0 + + # os.system('pdf2svg test_gprinter.pdf test_gprinter.svg')