pytex-preprocessor 1.0.3__tar.gz → 1.0.6__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.3 → pytex_preprocessor-1.0.6}/PKG-INFO +1 -1
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/pyproject.toml +1 -1
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_api/_compile.py +48 -1
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_builder/tectonic.py +78 -47
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_preprocessor.egg-info/PKG-INFO +1 -1
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/LICENSE +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/README.md +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/setup.cfg +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/__init__.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/commands/__init__.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/commands/biblatex.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/commands/builtin.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/commands/captions.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/commands/cleveref.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/commands/colors.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/commands/conditionals.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/commands/counters.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/commands/definitions.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/commands/floats.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/commands/font.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/commands/fontawesome.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/commands/fontspec.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/commands/geometry.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/commands/glossaries.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/commands/graphics.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/commands/hooks.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/commands/hyperref.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/commands/lengths.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/commands/listings.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/commands/mdframed.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/commands/picture.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/commands/setspace.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/commands/tables.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/helpers/__init__.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/helpers/coerce.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/helpers/parenting.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/helpers/sanitize.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/helpers/with_package.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/interface/__init__.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/interface/control_sequence.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/interface/package.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/interface/tex.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/model/__init__.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/model/color.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/model/comment.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/model/concat.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/model/control_sequence.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/model/document.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/model/document_class.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/model/empty.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/model/environment.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/model/image.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/model/include.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/model/length.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/model/math.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/model/package.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/model/raw.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/packages.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/registry.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/template.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_analyze/__init__.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_analyze/analyze.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_analyze/optimize.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_api/__init__.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_api/_models.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_api/_policy.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_api/_render.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_api/_sandbox.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_api/_security.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_api/sandbox_init.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_builder/__init__.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_builder/build.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_builder/console.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_builder/render.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_builder/tex2py.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_builder/tree.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_builder/variants.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_components/__init__.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_components/boxes.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_components/citations.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_components/cleveref_names.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_components/pagebreak.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_components/voting.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_components/watermark.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_components/wordcount.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/__init__.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/fonts/Blender/Blender-Bold.ttf +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/fonts/Blender/Blender-BoldItalic.ttf +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/fonts/Blender/Blender-Book.ttf +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/fonts/Blender/Blender-BookItalic.ttf +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/fonts/Blender/Blender-Medium.ttf +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/fonts/Blender/Blender-MediumItalic.ttf +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/fonts/Blender/Blender-Strong.ttf +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/fonts/Blender/Blender-Thin.ttf +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/fonts/Blender/Blender-ThinItalic.ttf +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/fonts/DIN/DIN-Black.ttf +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/fonts/DIN/DIN-Bold.ttf +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/fonts/DIN/DIN-BoldItalic.ttf +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/fonts/DIN/DIN-Italic.ttf +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/fonts/DIN/DIN-Medium.ttf +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/fonts/DIN/DIN-Regular.ttf +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/fonts/Times New Roman.ttf +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/logos/ASTA.svg +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/logos/DUMMY.png +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/logos/DUMMY_FOOT.png +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/logos/ECHO.svg +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/logos/HSRT.pdf +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/logos/INF.pdf +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/logos/MAKERS-Icon.svg +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/logos/MAKERS-RAlign.svg +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/logos/MAKERS.svg +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/logos/STUPA.pdf +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/logos/Skyline.pdf +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/colors.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/document.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/fonts.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/glossary.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/hyperref_config.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/listings.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/logos.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/pagesetup.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/tex/pagesetup.tex +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/titlepage.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/variants.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_koma/__init__.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_koma/commands.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_koma/document.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_markdown/__init__.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_markdown/convert.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_markdown/escape.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_markdown/frontmatter.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_markdown/glyphs.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_markdown/protocol/__init__.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_markdown/protocol/convert.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_markdown/protocol/document.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_markdown/protocol/entries.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_markdown/protocol/header.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_markdown/protocol/shortcodes.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_markdown/protocol/signatures.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_preprocessor.egg-info/SOURCES.txt +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_preprocessor.egg-info/dependency_links.txt +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_preprocessor.egg-info/entry_points.txt +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_preprocessor.egg-info/requires.txt +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_preprocessor.egg-info/top_level.txt +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_protocol/__init__.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_protocol/frontmatter.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_tikz/__init__.py +0 -0
- {pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_tikz/tikz.py +0 -0
|
@@ -102,18 +102,55 @@ def _kill_group(proc: subprocess.Popen[str]) -> None: # pragma: no cover - timi
|
|
|
102
102
|
proc.kill()
|
|
103
103
|
|
|
104
104
|
|
|
105
|
+
def _biber_env(
|
|
106
|
+
cmd: list[str], build_dir: Path, policy: TrustPolicy, console: Console
|
|
107
|
+
) -> dict[str, str] | None:
|
|
108
|
+
"""A child env whose PATH includes the biber matching the document's BCF.
|
|
109
|
+
|
|
110
|
+
Mirrors ``pytex_builder.tectonic.run_tectonic``: read the BCF (probing with a
|
|
111
|
+
no-op biber if it is not written yet) to pick the right biber release, then
|
|
112
|
+
ensure it (download+cache). Returns ``None`` (inherit env) for documents
|
|
113
|
+
without biblatex, or when biber can't be obtained (e.g. network disabled) —
|
|
114
|
+
tectonic then surfaces its own error rather than us masking it.
|
|
115
|
+
"""
|
|
116
|
+
tex = build_dir.parent / f"{_JOB}.tex"
|
|
117
|
+
try:
|
|
118
|
+
source = tex.read_text(encoding="utf-8", errors="ignore")
|
|
119
|
+
except OSError:
|
|
120
|
+
return None
|
|
121
|
+
# No biblatex → tectonic never invokes biber; skip the extra probe pass.
|
|
122
|
+
if "biblatex" not in source:
|
|
123
|
+
return None
|
|
124
|
+
try:
|
|
125
|
+
from pytex_builder.tectonic import biber_for_build, env_with_biber, probe_bcf
|
|
126
|
+
except Exception: # pragma: no cover - import guard
|
|
127
|
+
return None
|
|
128
|
+
job = _JOB
|
|
129
|
+
try:
|
|
130
|
+
biber = biber_for_build(build_dir, job, console)
|
|
131
|
+
if biber is None and policy.allow_network:
|
|
132
|
+
probe_bcf(cmd)
|
|
133
|
+
biber = biber_for_build(build_dir, job, console)
|
|
134
|
+
except Exception as exc: # pragma: no cover - infra
|
|
135
|
+
console.warn(f"biber setup skipped: {exc}")
|
|
136
|
+
return None
|
|
137
|
+
return env_with_biber(biber) if biber is not None else None
|
|
138
|
+
|
|
139
|
+
|
|
105
140
|
def _run_confined(
|
|
106
141
|
cmd: list[str],
|
|
107
142
|
cwd: Path,
|
|
108
143
|
limits: BuildLimits,
|
|
109
144
|
*,
|
|
110
145
|
apply_rlimits: bool,
|
|
146
|
+
env: Mapping[str, str] | None = None,
|
|
111
147
|
) -> tuple[int, str]:
|
|
112
148
|
"""Run ``cmd`` with rlimits + a hard wall-clock kill; return (rc, output).
|
|
113
149
|
|
|
114
150
|
``apply_rlimits`` is the in-process ``setrlimit`` floor; it is switched off
|
|
115
151
|
for the Podman path, where the container's cgroup flags do the capping (an
|
|
116
152
|
rlimit on the ``podman`` *client* would not reach the build inside).
|
|
153
|
+
``env`` overrides the child environment (e.g. a PATH that includes biber).
|
|
117
154
|
"""
|
|
118
155
|
posix = os.name == "posix"
|
|
119
156
|
preexec = make_rlimit_preexec(limits) if (apply_rlimits and posix) else None
|
|
@@ -126,6 +163,7 @@ def _run_confined(
|
|
|
126
163
|
text=True,
|
|
127
164
|
start_new_session=posix,
|
|
128
165
|
preexec_fn=preexec,
|
|
166
|
+
env=dict(env) if env is not None else None,
|
|
129
167
|
)
|
|
130
168
|
except OSError as exc:
|
|
131
169
|
raise CompileError(f"could not start tectonic: {exc}") from exc
|
|
@@ -256,8 +294,17 @@ def compile_to_pdf(
|
|
|
256
294
|
)
|
|
257
295
|
binary = _locate_tectonic(policy, console)
|
|
258
296
|
cmd = build_tectonic_cmd(binary, tex_file, build_dir, policy)
|
|
297
|
+
# biblatex docs (report/protocol) make tectonic shell out to ``biber``;
|
|
298
|
+
# it is not bundled, so provide a version-matched one on PATH (probe the
|
|
299
|
+
# BCF, then download+cache the matching biber). Without it tectonic dies
|
|
300
|
+
# with "Running external tool biber ... No such file or directory".
|
|
301
|
+
biber_env = _biber_env(cmd, build_dir, policy, console)
|
|
259
302
|
rc, out = _run_confined(
|
|
260
|
-
cmd,
|
|
303
|
+
cmd,
|
|
304
|
+
workdir,
|
|
305
|
+
req.limits,
|
|
306
|
+
apply_rlimits=policy.apply_rlimits,
|
|
307
|
+
env=biber_env,
|
|
261
308
|
)
|
|
262
309
|
|
|
263
310
|
log = truncate_log(out, req.limits)
|
|
@@ -21,7 +21,15 @@ import zipfile
|
|
|
21
21
|
from pathlib import Path
|
|
22
22
|
from typing import TYPE_CHECKING
|
|
23
23
|
|
|
24
|
-
__all__ = [
|
|
24
|
+
__all__ = [
|
|
25
|
+
"BuildError",
|
|
26
|
+
"biber_for_build",
|
|
27
|
+
"ensure_tectonic",
|
|
28
|
+
"env_with_biber",
|
|
29
|
+
"probe_bcf",
|
|
30
|
+
"run_makeindex",
|
|
31
|
+
"run_tectonic",
|
|
32
|
+
]
|
|
25
33
|
|
|
26
34
|
if TYPE_CHECKING:
|
|
27
35
|
from .console import Console
|
|
@@ -254,26 +262,6 @@ def _biber_cached(version: str) -> Path:
|
|
|
254
262
|
return CACHE_DIR / "biber" / version / name
|
|
255
263
|
|
|
256
264
|
|
|
257
|
-
def _biber_sources(version: str) -> list[tuple[str, str | None]]:
|
|
258
|
-
"""``(url, expected_sha256 or None)`` to try in order.
|
|
259
|
-
|
|
260
|
-
For each platform candidate the mirror is tried first, then SourceForge.
|
|
261
|
-
"""
|
|
262
|
-
sources: list[tuple[str, str | None]] = []
|
|
263
|
-
for sf_dir, filename, asset in _biber_candidates(version):
|
|
264
|
-
sha = BIBER_SHA256.get(asset)
|
|
265
|
-
sources.append((BIBER_MIRROR_URL.format(asset=asset), sha))
|
|
266
|
-
sources.append(
|
|
267
|
-
(
|
|
268
|
-
BIBER_RELEASE_URL.format(
|
|
269
|
-
version=version, sf_dir=sf_dir, filename=filename
|
|
270
|
-
),
|
|
271
|
-
sha,
|
|
272
|
-
)
|
|
273
|
-
)
|
|
274
|
-
return sources
|
|
275
|
-
|
|
276
|
-
|
|
277
265
|
def _is_biber_member(name: str) -> bool:
|
|
278
266
|
"""Whether an archive member is the biber executable.
|
|
279
267
|
|
|
@@ -335,11 +323,36 @@ def _download_to(url: str, dest: Path, sha: str | None, console: Console) -> boo
|
|
|
335
323
|
return True
|
|
336
324
|
|
|
337
325
|
|
|
326
|
+
def _biber_runs(binary: Path) -> bool:
|
|
327
|
+
"""``True`` if ``binary`` actually executes here (``biber --version`` exits 0).
|
|
328
|
+
|
|
329
|
+
The musl build is offered first (no glibc shared-lib deps) but is *dynamically*
|
|
330
|
+
linked against the musl loader; on a glibc-only host (e.g. Debian-slim) it
|
|
331
|
+
cannot exec at all ("No such file or directory"). Running it is the only
|
|
332
|
+
reliable cross-check, so we verify and fall back to the glibc build."""
|
|
333
|
+
try:
|
|
334
|
+
proc = subprocess.run(
|
|
335
|
+
[str(binary), "--version"], capture_output=True, timeout=30
|
|
336
|
+
)
|
|
337
|
+
except OSError:
|
|
338
|
+
return False
|
|
339
|
+
return proc.returncode == 0
|
|
340
|
+
|
|
341
|
+
|
|
338
342
|
def _ensure_biber(version: str, console: Console) -> Path:
|
|
339
|
-
"""Return a path to biber *version*, downloading from the mirror or SourceForge.
|
|
343
|
+
"""Return a path to biber *version*, downloading from the mirror or SourceForge.
|
|
344
|
+
|
|
345
|
+
Each platform candidate (musl first, then glibc) is downloaded, extracted and
|
|
346
|
+
**test-run**; the first one that actually executes here is cached. This makes
|
|
347
|
+
the choice robust on hosts that lack the musl loader or a glibc dependency."""
|
|
340
348
|
cached = _biber_cached(version)
|
|
341
349
|
if cached.exists():
|
|
342
|
-
|
|
350
|
+
# Re-validate: a cache poisoned by an earlier release (e.g. a musl binary
|
|
351
|
+
# that cannot exec here) must be replaced, not blindly reused.
|
|
352
|
+
if _biber_runs(cached):
|
|
353
|
+
return cached
|
|
354
|
+
console.detail("cached biber does not execute here; re-downloading")
|
|
355
|
+
cached.unlink(missing_ok=True)
|
|
343
356
|
|
|
344
357
|
if not shutil.which("curl"):
|
|
345
358
|
raise BuildError(
|
|
@@ -349,31 +362,49 @@ def _ensure_biber(version: str, console: Console) -> Path:
|
|
|
349
362
|
console.step(f"Downloading biber {version}")
|
|
350
363
|
cached.parent.mkdir(parents=True, exist_ok=True)
|
|
351
364
|
tmp = cached.parent / "biber.download"
|
|
365
|
+
cand = cached.parent / "biber.candidate"
|
|
366
|
+
last: str | None = None
|
|
352
367
|
try:
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
368
|
+
for sf_dir, filename, asset in _biber_candidates(version):
|
|
369
|
+
sha = BIBER_SHA256.get(asset)
|
|
370
|
+
urls = [
|
|
371
|
+
BIBER_MIRROR_URL.format(asset=asset),
|
|
372
|
+
BIBER_RELEASE_URL.format(
|
|
373
|
+
version=version, sf_dir=sf_dir, filename=filename
|
|
374
|
+
),
|
|
375
|
+
]
|
|
376
|
+
downloaded = False
|
|
377
|
+
for url in urls:
|
|
378
|
+
console.detail(f"source: {url}")
|
|
379
|
+
if _download_to(url, tmp, sha, console):
|
|
380
|
+
downloaded = True
|
|
381
|
+
break
|
|
382
|
+
if not downloaded:
|
|
383
|
+
last = f"{asset}: download failed"
|
|
384
|
+
continue
|
|
385
|
+
try:
|
|
386
|
+
cand.write_bytes(_extract_biber_binary(tmp, version))
|
|
387
|
+
cand.chmod(0o755)
|
|
388
|
+
except Exception as exc:
|
|
389
|
+
last = f"{asset}: extract failed ({exc})"
|
|
390
|
+
continue
|
|
391
|
+
if _biber_runs(cand):
|
|
392
|
+
cand.replace(cached)
|
|
393
|
+
cached.chmod(0o755)
|
|
394
|
+
return cached
|
|
395
|
+
last = f"{asset}: does not execute on this platform"
|
|
396
|
+
cand.unlink(missing_ok=True)
|
|
397
|
+
raise BuildError(f"failed to obtain a working biber {version} ({last})")
|
|
364
398
|
except Exception:
|
|
365
399
|
if cached.exists():
|
|
366
400
|
cached.unlink()
|
|
367
401
|
raise
|
|
368
402
|
finally:
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
cached.chmod(0o755)
|
|
373
|
-
return cached
|
|
403
|
+
tmp.unlink(missing_ok=True)
|
|
404
|
+
cand.unlink(missing_ok=True)
|
|
374
405
|
|
|
375
406
|
|
|
376
|
-
def
|
|
407
|
+
def biber_for_build(build_dir: Path, job: str, console: Console) -> Path | None:
|
|
377
408
|
"""Return a correctly-versioned biber if the BCF file reveals a mismatch."""
|
|
378
409
|
bcf = build_dir / f"{job}.bcf"
|
|
379
410
|
if not bcf.exists():
|
|
@@ -400,13 +431,13 @@ def _biber_for_build(build_dir: Path, job: str, console: Console) -> Path | None
|
|
|
400
431
|
return _ensure_biber(biber_ver, console)
|
|
401
432
|
|
|
402
433
|
|
|
403
|
-
def
|
|
434
|
+
def env_with_biber(biber: Path) -> dict[str, str]:
|
|
404
435
|
env = os.environ.copy()
|
|
405
436
|
env["PATH"] = str(biber.parent) + os.pathsep + env.get("PATH", "")
|
|
406
437
|
return env
|
|
407
438
|
|
|
408
439
|
|
|
409
|
-
def
|
|
440
|
+
def probe_bcf(cmd: list[str]) -> None:
|
|
410
441
|
"""Run tectonic with a no-op biber so the BCF file is written to build_dir.
|
|
411
442
|
|
|
412
443
|
Tectonic cleans up intermediates when biber fails, so the BCF is never
|
|
@@ -419,7 +450,7 @@ def _probe_bcf(cmd: list[str]) -> None:
|
|
|
419
450
|
fake = tmpdir / "biber"
|
|
420
451
|
fake.write_text("#!/bin/sh\nexit 0\n")
|
|
421
452
|
fake.chmod(0o755)
|
|
422
|
-
subprocess.run(cmd, env=
|
|
453
|
+
subprocess.run(cmd, env=env_with_biber(fake), capture_output=True)
|
|
423
454
|
finally:
|
|
424
455
|
shutil.rmtree(tmpdir, ignore_errors=True)
|
|
425
456
|
|
|
@@ -453,12 +484,12 @@ def run_tectonic(
|
|
|
453
484
|
# Determine the right biber from the BCF. If no BCF exists yet (first build
|
|
454
485
|
# or after a clean), run a silent probe pass with a no-op biber so tectonic
|
|
455
486
|
# writes the BCF to build_dir without actually needing biber installed.
|
|
456
|
-
biber =
|
|
487
|
+
biber = biber_for_build(build_dir, job, console)
|
|
457
488
|
if biber is None:
|
|
458
|
-
|
|
459
|
-
biber =
|
|
489
|
+
probe_bcf(cmd)
|
|
490
|
+
biber = biber_for_build(build_dir, job, console)
|
|
460
491
|
|
|
461
|
-
env =
|
|
492
|
+
env = env_with_biber(biber) if biber is not None else None
|
|
462
493
|
proc = subprocess.run(cmd, env=env)
|
|
463
494
|
if proc.returncode != 0:
|
|
464
495
|
log = build_dir / f"{tex_file.stem}.log"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex/interface/control_sequence.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_components/cleveref_names.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/logos/ASTA.svg
RENAMED
|
File without changes
|
{pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/logos/DUMMY.png
RENAMED
|
File without changes
|
|
File without changes
|
{pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/logos/ECHO.svg
RENAMED
|
File without changes
|
{pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/logos/HSRT.pdf
RENAMED
|
File without changes
|
{pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/logos/INF.pdf
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/logos/MAKERS.svg
RENAMED
|
File without changes
|
{pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/logos/STUPA.pdf
RENAMED
|
File without changes
|
{pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/assets/logos/Skyline.pdf
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/hyperref_config.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_hsrtreport/tex/pagesetup.tex
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_markdown/protocol/__init__.py
RENAMED
|
File without changes
|
{pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_markdown/protocol/convert.py
RENAMED
|
File without changes
|
{pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_markdown/protocol/document.py
RENAMED
|
File without changes
|
{pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_markdown/protocol/entries.py
RENAMED
|
File without changes
|
|
File without changes
|
{pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_markdown/protocol/shortcodes.py
RENAMED
|
File without changes
|
{pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_markdown/protocol/signatures.py
RENAMED
|
File without changes
|
{pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_preprocessor.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_preprocessor.egg-info/requires.txt
RENAMED
|
File without changes
|
{pytex_preprocessor-1.0.3 → pytex_preprocessor-1.0.6}/src/pytex_preprocessor.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|