pytex-preprocessor 1.0.6__tar.gz → 1.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/PKG-INFO +195 -176
- pytex_preprocessor-1.2.0/README.md +359 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/pyproject.toml +20 -19
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/__init__.py +10 -2
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/commands/__init__.py +7 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/commands/biblatex.py +2 -1
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/commands/builtin.py +34 -8
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/commands/captions.py +23 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/commands/cleveref.py +23 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/commands/colors.py +15 -2
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/commands/conditionals.py +31 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/commands/counters.py +33 -1
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/commands/definitions.py +12 -2
- pytex_preprocessor-1.2.0/src/pytex/commands/floats.py +160 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/commands/font.py +5 -4
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/commands/fontawesome.py +27 -4
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/commands/fontspec.py +35 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/commands/geometry.py +15 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/commands/glossaries.py +3 -2
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/commands/graphics.py +38 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/commands/hooks.py +32 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/commands/hyperref.py +23 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/commands/lengths.py +4 -4
- pytex_preprocessor-1.2.0/src/pytex/commands/listings.py +107 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/commands/mdframed.py +21 -0
- pytex_preprocessor-1.2.0/src/pytex/commands/picture.py +50 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/commands/setspace.py +15 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/commands/tables.py +11 -5
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/helpers/__init__.py +2 -0
- pytex_preprocessor-1.2.0/src/pytex/helpers/coerce.py +22 -0
- pytex_preprocessor-1.2.0/src/pytex/helpers/parenting.py +24 -0
- pytex_preprocessor-1.2.0/src/pytex/helpers/sanitize.py +70 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/helpers/with_package.py +19 -2
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/interface/__init__.py +2 -0
- pytex_preprocessor-1.2.0/src/pytex/interface/control_sequence.py +47 -0
- pytex_preprocessor-1.2.0/src/pytex/interface/package.py +70 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/interface/tex.py +17 -4
- pytex_preprocessor-1.2.0/src/pytex/model/__init__.py +26 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/model/color.py +84 -14
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/model/comment.py +8 -4
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/model/concat.py +16 -7
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/model/control_sequence.py +19 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/model/document.py +45 -14
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/model/empty.py +6 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/model/image.py +60 -21
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/model/include.py +9 -0
- pytex_preprocessor-1.2.0/src/pytex/model/length.py +100 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/model/math.py +8 -6
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/model/package.py +29 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/model/raw.py +28 -4
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/packages.py +14 -5
- pytex_preprocessor-1.2.0/src/pytex/registry.py +80 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/template.py +29 -18
- pytex_preprocessor-1.2.0/src/pytex_analyze/__init__.py +18 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_analyze/analyze.py +23 -7
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_analyze/optimize.py +81 -42
- pytex_preprocessor-1.2.0/src/pytex_api/__init__.py +223 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_api/_compile.py +147 -63
- pytex_preprocessor-1.2.0/src/pytex_api/_models.py +161 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_api/_policy.py +39 -29
- pytex_preprocessor-1.2.0/src/pytex_api/_render.py +199 -0
- pytex_preprocessor-1.2.0/src/pytex_api/_sandbox.py +540 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_api/_security.py +78 -37
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_api/sandbox_init.py +70 -29
- pytex_preprocessor-1.2.0/src/pytex_builder/__init__.py +8 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_builder/build.py +90 -66
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_builder/console.py +8 -7
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_builder/render.py +40 -24
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_builder/tectonic.py +132 -71
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_builder/tex2py.py +18 -13
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_builder/tree.py +36 -17
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_builder/variants.py +125 -55
- pytex_preprocessor-1.2.0/src/pytex_components/__init__.py +73 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_components/boxes.py +81 -35
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_components/citations.py +6 -4
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_components/cleveref_names.py +5 -1
- pytex_preprocessor-1.2.0/src/pytex_components/pagebreak.py +107 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_components/voting.py +27 -9
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_components/watermark.py +31 -4
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_components/wordcount.py +11 -2
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/__init__.py +5 -2
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/colors.py +6 -1
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/document.py +97 -42
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/fonts.py +16 -10
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/glossary.py +12 -7
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/hyperref_config.py +11 -4
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/listings.py +8 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/logos.py +74 -34
- pytex_preprocessor-1.2.0/src/pytex_hsrtreport/pagesetup.py +41 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/titlepage.py +28 -18
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/variants.py +17 -6
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_koma/document.py +13 -4
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_markdown/__init__.py +24 -13
- pytex_preprocessor-1.2.0/src/pytex_markdown/convert.py +633 -0
- pytex_preprocessor-1.2.0/src/pytex_markdown/escape.py +11 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_markdown/frontmatter.py +39 -30
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_markdown/glyphs.py +61 -52
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_markdown/protocol/__init__.py +8 -7
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_markdown/protocol/convert.py +38 -25
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_markdown/protocol/document.py +39 -19
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_markdown/protocol/entries.py +24 -10
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_markdown/protocol/header.py +25 -9
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_markdown/protocol/shortcodes.py +26 -13
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_markdown/protocol/signatures.py +18 -11
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_preprocessor.egg-info/PKG-INFO +195 -176
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_protocol/__init__.py +8 -6
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_protocol/frontmatter.py +1 -1
- pytex_preprocessor-1.0.6/README.md +0 -340
- pytex_preprocessor-1.0.6/src/pytex/commands/floats.py +0 -93
- pytex_preprocessor-1.0.6/src/pytex/commands/listings.py +0 -63
- pytex_preprocessor-1.0.6/src/pytex/commands/picture.py +0 -32
- pytex_preprocessor-1.0.6/src/pytex/helpers/coerce.py +0 -13
- pytex_preprocessor-1.0.6/src/pytex/helpers/parenting.py +0 -13
- pytex_preprocessor-1.0.6/src/pytex/helpers/sanitize.py +0 -59
- pytex_preprocessor-1.0.6/src/pytex/interface/control_sequence.py +0 -29
- pytex_preprocessor-1.0.6/src/pytex/interface/package.py +0 -52
- pytex_preprocessor-1.0.6/src/pytex/model/__init__.py +0 -25
- pytex_preprocessor-1.0.6/src/pytex/model/length.py +0 -54
- pytex_preprocessor-1.0.6/src/pytex/registry.py +0 -49
- pytex_preprocessor-1.0.6/src/pytex_analyze/__init__.py +0 -16
- pytex_preprocessor-1.0.6/src/pytex_api/__init__.py +0 -197
- pytex_preprocessor-1.0.6/src/pytex_api/_models.py +0 -125
- pytex_preprocessor-1.0.6/src/pytex_api/_render.py +0 -123
- pytex_preprocessor-1.0.6/src/pytex_api/_sandbox.py +0 -442
- pytex_preprocessor-1.0.6/src/pytex_builder/__init__.py +0 -8
- pytex_preprocessor-1.0.6/src/pytex_components/__init__.py +0 -58
- pytex_preprocessor-1.0.6/src/pytex_components/pagebreak.py +0 -67
- pytex_preprocessor-1.0.6/src/pytex_hsrtreport/pagesetup.py +0 -33
- pytex_preprocessor-1.0.6/src/pytex_markdown/convert.py +0 -490
- pytex_preprocessor-1.0.6/src/pytex_markdown/escape.py +0 -11
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/LICENSE +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/setup.cfg +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/model/document_class.py +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex/model/environment.py +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/assets/fonts/Blender/Blender-Bold.ttf +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/assets/fonts/Blender/Blender-BoldItalic.ttf +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/assets/fonts/Blender/Blender-Book.ttf +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/assets/fonts/Blender/Blender-BookItalic.ttf +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/assets/fonts/Blender/Blender-Medium.ttf +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/assets/fonts/Blender/Blender-MediumItalic.ttf +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/assets/fonts/Blender/Blender-Strong.ttf +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/assets/fonts/Blender/Blender-Thin.ttf +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/assets/fonts/Blender/Blender-ThinItalic.ttf +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/assets/fonts/DIN/DIN-Black.ttf +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/assets/fonts/DIN/DIN-Bold.ttf +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/assets/fonts/DIN/DIN-BoldItalic.ttf +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/assets/fonts/DIN/DIN-Italic.ttf +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/assets/fonts/DIN/DIN-Medium.ttf +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/assets/fonts/DIN/DIN-Regular.ttf +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/assets/fonts/Times New Roman.ttf +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/assets/logos/ASTA.svg +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/assets/logos/DUMMY.png +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/assets/logos/DUMMY_FOOT.png +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/assets/logos/ECHO.svg +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/assets/logos/HSRT.pdf +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/assets/logos/INF.pdf +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/assets/logos/MAKERS-Icon.svg +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/assets/logos/MAKERS-RAlign.svg +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/assets/logos/MAKERS.svg +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/assets/logos/STUPA.pdf +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/assets/logos/Skyline.pdf +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_hsrtreport/tex/pagesetup.tex +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_koma/__init__.py +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_koma/commands.py +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_preprocessor.egg-info/SOURCES.txt +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_preprocessor.egg-info/dependency_links.txt +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_preprocessor.egg-info/entry_points.txt +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_preprocessor.egg-info/requires.txt +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_preprocessor.egg-info/top_level.txt +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_tikz/__init__.py +0 -0
- {pytex_preprocessor-1.0.6 → pytex_preprocessor-1.2.0}/src/pytex_tikz/tikz.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pytex-preprocessor
|
|
3
|
-
Version: 1.0
|
|
3
|
+
Version: 1.2.0
|
|
4
4
|
Summary: Type-safe LaTeX document generation with Python
|
|
5
5
|
Author-email: Frederik Beimgraben <frederik@beimgraben.net>
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -692,62 +692,66 @@ Dynamic: license-file
|
|
|
692
692
|
|
|
693
693
|
# PyTeX
|
|
694
694
|
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
695
|
+
PyTeX builds a LaTeX document from Python, and a type checker can check the
|
|
696
|
+
Python code. You build the document as a node tree of typed `TeX` nodes. Then
|
|
697
|
+
you render it to a rendered `.tex` file. You can also put inline Python
|
|
698
|
+
expressions into an existing `.tex` source. PyTeX evaluates them when it
|
|
699
|
+
renders the file. PyTeX needs Python 3.13 or later.
|
|
699
700
|
|
|
700
|
-
A `TeX` node is
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
uses.
|
|
701
|
+
A `TeX` node is a dataclass with a `.rendered` property. Most node types are
|
|
702
|
+
immutable. The types `Document`, `Raw` and `IncludeImage` stay mutable. The
|
|
703
|
+
public API mirrors the LaTeX control sequences as PascalCase factories
|
|
704
|
+
(`Section`, `Bold`, `Frac`, `Title`, ...), so a document reads like the LaTeX
|
|
705
|
+
it renders. A node requires a package, so PyTeX assembles the preamble from
|
|
706
|
+
the package requirements that the body uses.
|
|
706
707
|
|
|
707
708
|
## Install
|
|
708
709
|
|
|
709
710
|
### Prebuilt binary
|
|
710
711
|
|
|
711
|
-
Each release attaches standalone `pytex`
|
|
712
|
-
Python
|
|
712
|
+
Each release attaches a standalone `pytex` binary for Linux, macOS and Windows.
|
|
713
|
+
The binary needs neither Python nor `pip`. Download one from the
|
|
713
714
|
[Releases](https://github.com/frederikbeimgraben/PyTeX-Preprocessor/releases)
|
|
714
|
-
page, make it executable, and run it.
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
`
|
|
719
|
-
|
|
715
|
+
page, make it executable, and run it.
|
|
716
|
+
|
|
717
|
+
The binary holds its own interpreter and common data packages. Those packages
|
|
718
|
+
are numpy, pandas, openpyxl and calamine for spreadsheets, Pillow, and PyYAML.
|
|
719
|
+
A document can `import` those without an install (see
|
|
720
|
+
[`packaging/`](packaging/)). PyTeX builds the binary on Python 3.14, so a
|
|
721
|
+
document can use `tex(t"...")` on a machine without Python 3.14. A build with
|
|
722
|
+
`--build` still needs the tectonic binary, which PyTeX downloads on first use.
|
|
720
723
|
|
|
721
724
|
### From PyPI
|
|
722
725
|
|
|
723
|
-
To
|
|
726
|
+
To get the `pytex` command everywhere, install it as an isolated tool with
|
|
724
727
|
[pipx](https://pipx.pypa.io/):
|
|
725
728
|
|
|
726
729
|
```sh
|
|
727
730
|
pipx install pytex-preprocessor
|
|
728
731
|
```
|
|
729
732
|
|
|
730
|
-
|
|
733
|
+
A plain `pip install pytex-preprocessor` also works.
|
|
731
734
|
|
|
732
|
-
For development, work in a virtualenv
|
|
735
|
+
For development, work in a virtualenv and make an editable install instead:
|
|
733
736
|
|
|
734
737
|
```sh
|
|
735
738
|
python -m venv venv && . venv/bin/activate
|
|
736
739
|
pip install -e . # add [dev] for pytest, ruff, basedpyright
|
|
737
740
|
```
|
|
738
741
|
|
|
739
|
-
|
|
742
|
+
PyTeX uses these external tools. Each tool serves one feature:
|
|
740
743
|
|
|
741
|
-
- `tectonic` —
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
- `
|
|
745
|
-
|
|
744
|
+
- `tectonic` — compiles the rendered `.tex` file to PDF (`--build`). If the
|
|
745
|
+
tectonic binary is not on `PATH`, PyTeX downloads a self-contained binary
|
|
746
|
+
into `$XDG_CACHE_HOME/pytex` or `~/.cache/pytex` and reuses it.
|
|
747
|
+
- `inkscape` — converts an `SVG` image to PDF.
|
|
748
|
+
- `makeindex` (from a TeX distribution, for example TeX Live) — resolves the
|
|
749
|
+
`glossaries` entries and the acronyms.
|
|
746
750
|
|
|
747
751
|
## Quick start
|
|
748
752
|
|
|
749
|
-
A `.tex.py` file is plain Python
|
|
750
|
-
a `TeX` node:
|
|
753
|
+
A `.tex.py` file is plain Python that defines the `__pytex__` node at module
|
|
754
|
+
level. That node holds a `TeX` node:
|
|
751
755
|
|
|
752
756
|
```py
|
|
753
757
|
from pytex.commands.builtin import Bold, Emph, Section, Title, MakeTitle
|
|
@@ -772,14 +776,15 @@ pytex example.tex.py # render -> build/example.out.tex
|
|
|
772
776
|
pytex example.tex.py --build # render + compile -> build/example.out.pdf
|
|
773
777
|
```
|
|
774
778
|
|
|
775
|
-
|
|
779
|
+
PyTeX coerces a bare string to a text node and escapes it for LaTeX.
|
|
776
780
|
|
|
777
781
|
### Template strings (Python 3.14+)
|
|
778
782
|
|
|
779
783
|
On Python 3.14, `pytex.tex` accepts a [PEP 750](https://peps.python.org/pep-0750/)
|
|
780
|
-
template string and builds a
|
|
781
|
-
|
|
782
|
-
|
|
784
|
+
template string and builds a node tree from it. The static parts stay literal
|
|
785
|
+
LaTeX. For an interpolation, `tex` escapes a plain value for LaTeX, and puts a
|
|
786
|
+
`TeX` node into the node tree without a change. It handles a nested template
|
|
787
|
+
string, a list and a tuple the same way:
|
|
783
788
|
|
|
784
789
|
```py
|
|
785
790
|
from pytex import tex
|
|
@@ -788,22 +793,23 @@ name = "Q&A: 50%"
|
|
|
788
793
|
body = tex(t"{Bold('Heading')} — {name}") # node spliced; name -> "Q\&A: 50\%"
|
|
789
794
|
```
|
|
790
795
|
|
|
791
|
-
`tex`
|
|
796
|
+
PyTeX exports `tex` only on Python 3.14 and later. The rest of the library runs
|
|
797
|
+
on Python 3.13.
|
|
792
798
|
|
|
793
799
|
## The `pytex` command
|
|
794
800
|
|
|
795
|
-
|
|
801
|
+
PyTeX dispatches the input file by its extension:
|
|
796
802
|
|
|
797
803
|
| Extension | Handling |
|
|
798
804
|
| --- | --- |
|
|
799
|
-
| `.py` |
|
|
800
|
-
| `.tex` |
|
|
801
|
-
| `.md` / `.markdown` |
|
|
805
|
+
| `.py` | PyTeX imports the file as a module and renders its `__pytex__` node. By convention, name the file `<doc>.tex.py`. |
|
|
806
|
+
| `.tex` | PyTeX wraps the file in `IncludeTeX`, evaluates each inline `pytex(...)` marker, then renders the file. By convention, name the file `<doc>.py.tex`. |
|
|
807
|
+
| `.md` / `.markdown` | The Markdown converter turns the file into nodes. PyTeX wraps them in a document that `--variant` picks (see below). Without `--variant`, PyTeX detects the variant. |
|
|
802
808
|
|
|
803
|
-
### Inline
|
|
809
|
+
### Inline `pytex(...)` markers in `.tex`
|
|
804
810
|
|
|
805
|
-
|
|
806
|
-
is a LaTeX no-op, so
|
|
811
|
+
Every registered factory is in scope inside a marker. The `\iffalse ... \fi`
|
|
812
|
+
pair is a LaTeX no-op, so LaTeX still compiles the source without PyTeX:
|
|
807
813
|
|
|
808
814
|
```tex
|
|
809
815
|
Today is \iffalse{pytex(Today())}\fi.
|
|
@@ -815,73 +821,76 @@ Plain Python works too: $3^2 = \iffalse{pytex(3 ** 2)}\fi$.
|
|
|
815
821
|
|
|
816
822
|
| Flag | Default | Meaning |
|
|
817
823
|
| --- | --- | --- |
|
|
818
|
-
| `-o`, `--output` | `<build-dir>/<input>.out.tex` | rendered
|
|
819
|
-
| `-b`, `--build` | off | compile the rendered `.tex` to PDF with tectonic |
|
|
820
|
-
| `--build-dir DIR` | `build` | directory for artifacts and tectonic output |
|
|
821
|
-
| `--no-shell-escape` | shell-escape on |
|
|
822
|
-
| `-t`, `--tree` | off | also print the
|
|
823
|
-
| `-f`, `--force` | off | skip the optimize
|
|
824
|
-
| `--variant STYLE` | auto-detect | Markdown
|
|
825
|
-
| `--config JSON` | none | JSON object of document-class
|
|
826
|
-
| `--untrusted` | off (trusted) | render
|
|
827
|
-
| `--trust-level LEVEL` | `trusted` | `trusted`, `sandboxed`, or `untrusted` (see [Security](#security-and-trust)) |
|
|
828
|
-
|
|
829
|
-
Shell-escape is on by default because inline
|
|
830
|
-
|
|
831
|
-
`glossaries
|
|
824
|
+
| `-o`, `--output` | `<build-dir>/<input>.out.tex` | path of the rendered `.tex` file |
|
|
825
|
+
| `-b`, `--build` | off | compile the rendered `.tex` file to PDF with the tectonic binary |
|
|
826
|
+
| `--build-dir DIR` | `build` | build directory for the artifacts and the tectonic output |
|
|
827
|
+
| `--no-shell-escape` | shell-escape on | turn shell-escape off |
|
|
828
|
+
| `-t`, `--tree` | off | also print the node tree of the input file in `tree` style before the render |
|
|
829
|
+
| `-f`, `--force` | off | skip the optimize pass and the analysis pass, and build even when PyTeX finds a problem |
|
|
830
|
+
| `--variant STYLE` | auto-detect | variant for a Markdown input file (`plain`, `report`, `report-makers`, `protocol`, `protocol-asta`, `protocol-stupa`) |
|
|
831
|
+
| `--config JSON` | none | JSON object of document-class parameters. `--config` overrides the frontmatter. |
|
|
832
|
+
| `--untrusted` | off (trusted) | render input from a source you do not trust through the trust policy (see [Security](#security-and-trust)) |
|
|
833
|
+
| `--trust-level LEVEL` | `trusted` | the trust level: `trusted`, `sandboxed`, or `untrusted` (see [Security](#security-and-trust)) |
|
|
834
|
+
|
|
835
|
+
Shell-escape is on by default, because an inline image decodes its base64
|
|
836
|
+
data during the compile pass. The build runs the tectonic binary, then the
|
|
837
|
+
makeindex step for `glossaries` and the acronyms. When the makeindex step
|
|
838
|
+
rebuilds an index, the build runs one more compile pass.
|
|
832
839
|
|
|
833
840
|
### Security and trust
|
|
834
841
|
|
|
835
|
-
By default the
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
`--trust-level {sandboxed,untrusted}`).
|
|
844
|
-
`pytex_api` trust policy
|
|
845
|
-
|
|
846
|
-
- refuses `.py`
|
|
847
|
-
- leaves
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
842
|
+
By default the `pytex` command runs at trust level `trusted`. At that level
|
|
843
|
+
PyTeX imports and executes a `.py` input file. It evaluates each inline
|
|
844
|
+
`pytex(...)` marker of a `.tex` input file and each Markdown `eval` comment. It
|
|
845
|
+
also turns shell-escape on. This is code execution by design, because that is
|
|
846
|
+
how a PyTeX document works. **Use the default only on a document you wrote
|
|
847
|
+
yourself.**
|
|
848
|
+
|
|
849
|
+
If the input file comes from a source you do not trust, pass `--untrusted` (or
|
|
850
|
+
`--trust-level {sandboxed,untrusted}`). Both options route the build through
|
|
851
|
+
the `pytex_api` trust policy. The trust policy:
|
|
852
|
+
|
|
853
|
+
- refuses a `.py` or `.tex.py` input file, so PyTeX executes no Python,
|
|
854
|
+
- leaves each inline `pytex(...)` marker and each Markdown `eval` comment
|
|
855
|
+
inert,
|
|
856
|
+
- forces shell-escape **off**, and rejects a package that opens a
|
|
857
|
+
code-execution surface (`minted`, `shellesc`, `pythontex`, …) and every
|
|
858
|
+
package off the package allowlist,
|
|
859
|
+
- applies the CPU, memory and output limits, and
|
|
860
|
+
- needs the Podman sandbox for a PDF build at both trust levels. The level
|
|
861
|
+
`sandboxed` has a wider package allowlist than `untrusted`.
|
|
862
|
+
|
|
863
|
+
`--untrusted` is shorthand for `--trust-level untrusted`. The two options are
|
|
864
|
+
mutually exclusive. The default trust level is `trusted`, so an existing
|
|
865
|
+
command line does not change.
|
|
866
|
+
|
|
867
|
+
The `pytex` command prints short, color-tagged output (`==>`, `note:`,
|
|
868
|
+
`warning:`, `error:`) in the style of tectonic. On a failure it names the
|
|
869
|
+
likely cause and the log file. Set `NO_COLOR` to turn color off.
|
|
870
|
+
|
|
871
|
+
### The optimize pass and the analysis pass
|
|
872
|
+
|
|
873
|
+
Before PyTeX renders the node tree, it runs the optimize pass and then the
|
|
874
|
+
analysis pass. The optimize pass tidies the node tree. It flattens a nested
|
|
875
|
+
`Concat`, drops an empty node, and turns a whole-`Raw` LaTeX construct into a
|
|
876
|
+
native node. It also expands each inline `pytex(...)` marker, and turns a `Raw`
|
|
877
|
+
comment and `Raw` math (`\[...\]`, `\(...\)`, `$...$`) into a native node. The
|
|
878
|
+
optimize pass is render-equivalent. The analysis pass then runs static checks
|
|
879
|
+
for problems that LaTeX reports late or not at all:
|
|
880
|
+
|
|
881
|
+
- a reference (`\ref`, `\cref`, `\autoref`, ...) to a label that no node
|
|
882
|
+
defines,
|
|
883
|
+
- a label that more than one node defines,
|
|
884
|
+
- an `\includegraphics` path that does not exist on disk.
|
|
885
|
+
|
|
886
|
+
A missing image is an error and stops the build. Every other issue is a
|
|
887
|
+
warning. To skip both passes and build anyway, pass `-f` or `--force`.
|
|
879
888
|
|
|
880
889
|
### Inspecting the node tree
|
|
881
890
|
|
|
882
|
-
`--tree` prints the
|
|
883
|
-
|
|
884
|
-
|
|
891
|
+
`--tree` prints the node tree of the input file, then renders or builds as
|
|
892
|
+
usual. Use it to see how PyTeX maps an input file to nodes. A node that
|
|
893
|
+
requires a package carries a tag with the package name (`[+package]`):
|
|
885
894
|
|
|
886
895
|
```
|
|
887
896
|
$ pytex example.tex.py --tree
|
|
@@ -897,22 +906,24 @@ Document (article)
|
|
|
897
906
|
|
|
898
907
|
## Packages
|
|
899
908
|
|
|
900
|
-
`pytex` is the core
|
|
909
|
+
`pytex` is the core package. Every other package is optional and builds on
|
|
910
|
+
`pytex`.
|
|
901
911
|
|
|
902
912
|
| Package | Provides |
|
|
903
913
|
| --- | --- |
|
|
904
|
-
| `pytex` | core node model, `Document`, math, tables, graphics, and factories for the common LaTeX packages (biblatex, cleveref, glossaries, hyperref, listings, ...). |
|
|
905
|
-
| `pytex_koma` | KOMA-Script classes and commands (`Addchap`, `Minisec`, `KOMAoptions`, ...). |
|
|
914
|
+
| `pytex` | the core node model, `Document`, math, tables, graphics, and the factories for the common LaTeX packages (biblatex, cleveref, glossaries, hyperref, listings, ...). |
|
|
915
|
+
| `pytex_koma` | the KOMA-Script classes and commands (`Addchap`, `Minisec`, `KOMAoptions`, ...). |
|
|
906
916
|
| `pytex_tikz` | TikZ pictures and primitives (`TikzPicture`, `Draw`, `Node`, `Circle`, ...). |
|
|
907
|
-
| `pytex_components` |
|
|
908
|
-
| `pytex_markdown` | Markdown
|
|
909
|
-
| `pytex_analyze` | static checks over the node tree
|
|
910
|
-
| `pytex_hsrtreport` | HSRT report document class, title pages, logos, and HSRT
|
|
911
|
-
| `pytex_protocol` | deprecated alias for `pytex_markdown.protocol
|
|
917
|
+
| `pytex_components` | the components that any document can use: colored boxes (`ColoredBox` and the presets), a voting tally, a draft watermark, word-count and smart-pagebreak macros, a clickable author-year citation, and German cleveref labels. |
|
|
918
|
+
| `pytex_markdown` | the Markdown converter, which turns Markdown into native `TeX` nodes (see below). It holds `pytex_markdown.protocol` for a StuPa or AStA meeting protocol, and `pytex_markdown.frontmatter` for the YAML frontmatter. |
|
|
919
|
+
| `pytex_analyze` | the analysis pass, which runs static checks over the node tree for a dangling reference, a duplicate label and a missing image. It also holds `Optimize`, the render-equivalent optimize pass. |
|
|
920
|
+
| `pytex_hsrtreport` | the HSRT report document class, the title pages, the logos, and the HSRT color, font and glossary helpers. It builds on `pytex_components` and re-exports it, so an older import keeps working. |
|
|
921
|
+
| `pytex_protocol` | the deprecated alias for `pytex_markdown.protocol`. It stays as a re-export shim. |
|
|
912
922
|
|
|
913
923
|
## Markdown
|
|
914
924
|
|
|
915
|
-
`pytex_markdown`
|
|
925
|
+
The Markdown converter in `pytex_markdown` turns Markdown into native `TeX`
|
|
926
|
+
nodes. It parses the source with `marko`:
|
|
916
927
|
|
|
917
928
|
```py
|
|
918
929
|
from pytex_markdown import Markdown, IncludeMarkdown
|
|
@@ -921,83 +932,88 @@ body = Markdown("# Title\n\nText with **bold**, `code`, [a link](https://x).")
|
|
|
921
932
|
body = IncludeMarkdown("notes.md", base_level=-1) # base_level=-1: # -> \chapter
|
|
922
933
|
```
|
|
923
934
|
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
935
|
+
A heading, emphasis, inline code and fenced code map to the core `pytex`
|
|
936
|
+
library. A list, a link, an image, a GFM table, a block quote and a thematic
|
|
937
|
+
break map to it too. The Markdown converter escapes the text for LaTeX. It adds
|
|
938
|
+
these extras to plain Markdown:
|
|
927
939
|
|
|
928
|
-
- **GitHub-style callouts** become colored boxes
|
|
940
|
+
- **GitHub-style callouts** become colored boxes from `pytex_components`:
|
|
929
941
|
```md
|
|
930
942
|
> [!NOTE] -> InfoBox > [!IMPORTANT] -> ImportantBox
|
|
931
943
|
> [!TIP] -> SuccessBox > [!WARNING] -> WarningBox
|
|
932
944
|
```
|
|
933
|
-
- **Citations** in Pandoc syntax
|
|
934
|
-
`[@a; @b]` ->
|
|
935
|
-
- **Bibliography** from frontmatter
|
|
936
|
-
`|` block scalar) or a path to a `.bib` file
|
|
937
|
-
`\printbibliography`.
|
|
938
|
-
- ASCII **math
|
|
939
|
-
**euro sign** `€` becomes a font-independent `\euro{}
|
|
940
|
-
vertical
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
945
|
+
- **Citations** in Pandoc syntax. `[@key]` and `[@key, p. 5]` -> `\autocite`,
|
|
946
|
+
`[@a; @b]` -> one combined cite, and a narrative `@key` -> `\textcite`.
|
|
947
|
+
- **Bibliography** from the frontmatter. The key `bibliography:` holds either
|
|
948
|
+
inline BibTeX (a `|` block scalar) or a path to a `.bib` file. A report
|
|
949
|
+
variant prints a numbered `\printbibliography`.
|
|
950
|
+
- An ASCII **math arrow** (`->`, `=>`, `<->`, ...) becomes an inline math
|
|
951
|
+
arrow. The **euro sign** `€` becomes a font-independent `\euro{}`. A table
|
|
952
|
+
gets more vertical space.
|
|
953
|
+
|
|
954
|
+
PyTeX registers both factories, so they also work in an inline `pytex(...)`
|
|
955
|
+
marker in a `.tex` input file.
|
|
944
956
|
|
|
945
957
|
### Output variants
|
|
946
958
|
|
|
947
|
-
When the `pytex` command renders a `.md` file it wraps the converted nodes in
|
|
948
|
-
document
|
|
959
|
+
When the `pytex` command renders a `.md` file, it wraps the converted nodes in
|
|
960
|
+
a document that `--variant` picks:
|
|
949
961
|
|
|
950
962
|
| Variant | Document |
|
|
951
963
|
| --- | --- |
|
|
952
|
-
| `plain` | a bare `Document
|
|
953
|
-
| `report` | an HSRT report with title page and table of contents
|
|
954
|
-
| `report-makers` | a `report`
|
|
955
|
-
| `protocol
|
|
956
|
-
| `protocol-
|
|
964
|
+
| `plain` | a bare `Document`. The default document class is `article`, and `#` -> `\section`. |
|
|
965
|
+
| `report` | an HSRT report with a title page and a table of contents. `#` -> `\chapter`. |
|
|
966
|
+
| `report-makers` | a `report` with the MAKERS logo on the title page and in the footer. |
|
|
967
|
+
| `protocol` | a meeting protocol with no corporate design of its own. The caller names the logos with `logos` and `footer_logos`. |
|
|
968
|
+
| `protocol-asta` | an AStA meeting protocol. It is an HSRT report with the AStA logos. |
|
|
969
|
+
| `protocol-stupa` | a StuPa meeting protocol. It is an HSRT report with the StuPa logos. |
|
|
957
970
|
|
|
958
|
-
Without `--variant`,
|
|
959
|
-
|
|
971
|
+
Without `--variant`, PyTeX detects the variant. Meeting-protocol frontmatter
|
|
972
|
+
(`gremium:` or `typ: protokoll`) picks a protocol variant. Every other input
|
|
973
|
+
file gets `plain`.
|
|
960
974
|
|
|
961
|
-
Document-class parameters come from the YAML frontmatter and from `--config
|
|
962
|
-
|
|
975
|
+
Document-class parameters come from the YAML frontmatter and from `--config`, a
|
|
976
|
+
JSON object. `--config` overrides the frontmatter. For example:
|
|
963
977
|
|
|
964
978
|
```sh
|
|
965
979
|
pytex notes.md --variant plain --config '{"documentclass": "scrartcl", "classoptions": ["11pt", "twocolumn"]}'
|
|
966
980
|
```
|
|
967
981
|
|
|
968
982
|
`classoptions` accepts a list (`"twocolumn"`, `"DIV=12"`) or a `{key: value}`
|
|
969
|
-
object.
|
|
970
|
-
`title
|
|
971
|
-
not also
|
|
972
|
-
|
|
973
|
-
The report
|
|
974
|
-
`keywords`, title-page `datalines` (a list of `"Label: value"` entries),
|
|
975
|
-
`bibliography` (see [Markdown](#markdown))
|
|
976
|
-
|
|
977
|
-
`
|
|
978
|
-
|
|
983
|
+
object. A variant with a title page, such as `report`, takes the title from
|
|
984
|
+
`title:` or from `--config`. If neither one gives a title, the variant takes
|
|
985
|
+
the first `#` heading, and then does not also render it as a chapter.
|
|
986
|
+
|
|
987
|
+
The report variants read more frontmatter keys. These are `author`, `abstract`,
|
|
988
|
+
`keywords`, the title-page `datalines` (a list of `"Label: value"` entries), and
|
|
989
|
+
`bibliography` (see [Markdown](#markdown)). The key `logos` names the title-page
|
|
990
|
+
logos, and the key `footer_logos` the logos of the page footer. Each one takes
|
|
991
|
+
a vendored name such as `INF` or `MAKERS`, a path to a custom image file, or
|
|
992
|
+
both. Without these keys, the variant supplies its own logos. The keys `abstract_heading` and `keywords_heading` rename
|
|
993
|
+
the default "Abstract" and "Keywords" sections.
|
|
979
994
|
|
|
980
995
|
## Converting LaTeX to PyTeX
|
|
981
996
|
|
|
982
|
-
`pytex-tex2py` turns an existing `.tex` file into an equivalent `.tex.py`
|
|
983
|
-
|
|
984
|
-
`pytex(...)`
|
|
985
|
-
result to Python that rebuilds the same
|
|
997
|
+
`pytex-tex2py` turns an existing `.tex` file into an equivalent `.tex.py` file.
|
|
998
|
+
It reads the file and runs the optimize pass over it. The optimize pass expands
|
|
999
|
+
each inline `pytex(...)` marker and recognizes comments and math.
|
|
1000
|
+
`pytex-tex2py` then serializes the result to Python that rebuilds the same node
|
|
1001
|
+
tree:
|
|
986
1002
|
|
|
987
1003
|
```sh
|
|
988
1004
|
pytex-tex2py paper.tex # -> paper.tex.py
|
|
989
1005
|
pytex-tex2py paper.tex -o out.py
|
|
990
1006
|
```
|
|
991
1007
|
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
conversion always round-trips.
|
|
1008
|
+
The rendered `.tex` file of the new `.tex.py` file matches the original byte
|
|
1009
|
+
for byte. A node that the serializer does not handle falls back to a literal
|
|
1010
|
+
`Raw`, so the conversion always round-trips.
|
|
995
1011
|
|
|
996
1012
|
## Examples
|
|
997
1013
|
|
|
998
|
-
|
|
999
|
-
mixed, and a full HSRT report
|
|
1000
|
-
resolve:
|
|
1014
|
+
The `examples/` directory holds one minimal input file per kind: `.tex.py`,
|
|
1015
|
+
`.py.tex`, `.md`, a mixed file, and a full HSRT report. Run the commands from
|
|
1016
|
+
the repository root, so the relative paths resolve:
|
|
1001
1017
|
|
|
1002
1018
|
```sh
|
|
1003
1019
|
pytex examples/document.tex.py --build
|
|
@@ -1007,24 +1023,27 @@ pytex examples/notes.md --build
|
|
|
1007
1023
|
|
|
1008
1024
|
## Stability
|
|
1009
1025
|
|
|
1010
|
-
From 1.0
|
|
1011
|
-
public API is what each package exports through its top-level `__all__
|
|
1012
|
-
|
|
1013
|
-
`pytex_tikz`, `pytex_components`, `pytex_markdown`,
|
|
1014
|
-
`
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1026
|
+
From 1.0 on, PyTeX follows [Semantic Versioning](https://semver.org). The
|
|
1027
|
+
public API is what each package exports through its top-level `__all__`. That
|
|
1028
|
+
is every name you can reach as `from pytex import X`, and the same for
|
|
1029
|
+
`pytex_koma`, `pytex_tikz`, `pytex_components`, `pytex_markdown`,
|
|
1030
|
+
`pytex_analyze` and `pytex_hsrtreport`. A change that breaks one of those names
|
|
1031
|
+
needs a major version bump.
|
|
1032
|
+
|
|
1033
|
+
The contract also covers the registry keys that an inline `pytex(...)` marker
|
|
1034
|
+
can use. A registry key is the name of a factory, so a rename of a registered
|
|
1035
|
+
factory is a breaking change. For that reason the `\fill` length is `Fill_len`,
|
|
1036
|
+
which leaves the bare `Fill` registry key to the TikZ path command.
|
|
1037
|
+
|
|
1038
|
+
Some parts are internal, and the guarantee does not cover them. A name with a
|
|
1039
|
+
leading underscore is internal. A module whose name starts with an underscore
|
|
1040
|
+
is internal, for example `pytex_api._policy` and `pytex_api._compile`. A name
|
|
1041
|
+
that a package does not list in its `__all__` is also internal. Import those at
|
|
1042
|
+
your own risk.
|
|
1043
|
+
|
|
1044
|
+
The deprecated shims `pytex_protocol` and the `pytex.commands.lengths.Fill`
|
|
1045
|
+
alias keep working and raise a `DeprecationWarning`. PyTeX may remove them in
|
|
1046
|
+
the next major release.
|
|
1028
1047
|
|
|
1029
1048
|
## License
|
|
1030
1049
|
|