Spaces:
Running
Running
Siyuan Hu
commited on
Commit
·
aab81af
1
Parent(s):
f3dfa83
feat(runtime): download tectonic on-the-fly into runs/_bin when not found; use for both poster and debug compiles
Browse files
app.py
CHANGED
|
@@ -354,6 +354,54 @@ def render_overleaf_button(overleaf_b64):
|
|
| 354 |
"""
|
| 355 |
return html
|
| 356 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 357 |
def _compile_poster_pdf(OUTPUT_DIR: Path, logs):
|
| 358 |
"""
|
| 359 |
Compile output/poster_latex_proj/poster_output.tex into a PDF using an
|
|
@@ -380,20 +428,8 @@ def _compile_poster_pdf(OUTPUT_DIR: Path, logs):
|
|
| 380 |
|
| 381 |
def _has(bin_name):
|
| 382 |
return _sh.which(bin_name) is not None
|
| 383 |
-
def _candidate_tectonic():
|
| 384 |
-
import os
|
| 385 |
-
cands = [
|
| 386 |
-
"tectonic",
|
| 387 |
-
str(Path("/usr/local/bin/tectonic")),
|
| 388 |
-
str(Path("/usr/bin/tectonic")),
|
| 389 |
-
os.path.expanduser("~/.local/bin/tectonic"),
|
| 390 |
-
]
|
| 391 |
-
for c in cands:
|
| 392 |
-
if _sh.which(c) or Path(c).exists():
|
| 393 |
-
return c
|
| 394 |
-
return None
|
| 395 |
|
| 396 |
-
tbin =
|
| 397 |
if tbin:
|
| 398 |
cmd = [tbin, tex_path.name]
|
| 399 |
logs.append("▶ Compiling with tectonic …")
|
|
@@ -457,19 +493,7 @@ def _compile_tex_to_pdf(tex_path: Path, logs):
|
|
| 457 |
import shutil as _sh, subprocess as _sp
|
| 458 |
def _has(bin_name):
|
| 459 |
return _sh.which(bin_name) is not None
|
| 460 |
-
|
| 461 |
-
import os
|
| 462 |
-
cands = [
|
| 463 |
-
"tectonic",
|
| 464 |
-
str(Path("/usr/local/bin/tectonic")),
|
| 465 |
-
str(Path("/usr/bin/tectonic")),
|
| 466 |
-
os.path.expanduser("~/.local/bin/tectonic"),
|
| 467 |
-
]
|
| 468 |
-
for c in cands:
|
| 469 |
-
if _sh.which(c) or Path(c).exists():
|
| 470 |
-
return c
|
| 471 |
-
return None
|
| 472 |
-
tbin = _candidate_tectonic()
|
| 473 |
if tbin:
|
| 474 |
cmd = [tbin, tex_path.name]
|
| 475 |
logs.append("▶ Compiling with tectonic …")
|
|
|
|
| 354 |
"""
|
| 355 |
return html
|
| 356 |
|
| 357 |
+
def _get_tectonic_bin(logs):
|
| 358 |
+
"""Return a usable path to the tectonic binary. Try PATH/common paths; if not found, download to runs/_bin."""
|
| 359 |
+
import shutil as _sh, tarfile, urllib.request, os
|
| 360 |
+
# 1) existing in PATH or common dirs
|
| 361 |
+
cands = [
|
| 362 |
+
"tectonic",
|
| 363 |
+
str(Path("/usr/local/bin/tectonic")),
|
| 364 |
+
str(Path("/usr/bin/tectonic")),
|
| 365 |
+
os.path.expanduser("~/.local/bin/tectonic"),
|
| 366 |
+
str((RUNS_DIR / "_bin" / "tectonic").resolve()),
|
| 367 |
+
]
|
| 368 |
+
for c in cands:
|
| 369 |
+
if _sh.which(c) or Path(c).exists():
|
| 370 |
+
return c
|
| 371 |
+
# 2) download to runs/_bin
|
| 372 |
+
try:
|
| 373 |
+
url = "https://github.com/tectonic-typesetting/tectonic/releases/download/tectonic%400.15.0/tectonic-0.15.0-x86_64-unknown-linux-gnu.tar.gz"
|
| 374 |
+
bin_dir = RUNS_DIR / "_bin"
|
| 375 |
+
bin_dir.mkdir(parents=True, exist_ok=True)
|
| 376 |
+
tgz = bin_dir / "tectonic.tar.gz"
|
| 377 |
+
logs.append("⬇️ Downloading tectonic binary …")
|
| 378 |
+
with urllib.request.urlopen(url, timeout=60) as resp, open(tgz, "wb") as out:
|
| 379 |
+
out.write(resp.read())
|
| 380 |
+
with tarfile.open(tgz, "r:gz") as tf:
|
| 381 |
+
tf.extractall(path=bin_dir)
|
| 382 |
+
# find binary
|
| 383 |
+
tbin = None
|
| 384 |
+
for p in bin_dir.rglob("tectonic"):
|
| 385 |
+
if p.is_file() and os.access(p, os.X_OK):
|
| 386 |
+
tbin = p
|
| 387 |
+
break
|
| 388 |
+
if not tbin:
|
| 389 |
+
# make executable if needed
|
| 390 |
+
for p in bin_dir.rglob("tectonic"):
|
| 391 |
+
try:
|
| 392 |
+
p.chmod(0o755)
|
| 393 |
+
tbin = p
|
| 394 |
+
break
|
| 395 |
+
except Exception:
|
| 396 |
+
continue
|
| 397 |
+
if tbin:
|
| 398 |
+
logs.append(f"✅ Tectonic ready at {tbin}")
|
| 399 |
+
return str(tbin)
|
| 400 |
+
logs.append("⚠️ Tectonic binary not found after download.")
|
| 401 |
+
except Exception as e:
|
| 402 |
+
logs.append(f"⚠️ Tectonic download failed: {e}")
|
| 403 |
+
return None
|
| 404 |
+
|
| 405 |
def _compile_poster_pdf(OUTPUT_DIR: Path, logs):
|
| 406 |
"""
|
| 407 |
Compile output/poster_latex_proj/poster_output.tex into a PDF using an
|
|
|
|
| 428 |
|
| 429 |
def _has(bin_name):
|
| 430 |
return _sh.which(bin_name) is not None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 431 |
|
| 432 |
+
tbin = _get_tectonic_bin(logs)
|
| 433 |
if tbin:
|
| 434 |
cmd = [tbin, tex_path.name]
|
| 435 |
logs.append("▶ Compiling with tectonic …")
|
|
|
|
| 493 |
import shutil as _sh, subprocess as _sp
|
| 494 |
def _has(bin_name):
|
| 495 |
return _sh.which(bin_name) is not None
|
| 496 |
+
tbin = _get_tectonic_bin(logs)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 497 |
if tbin:
|
| 498 |
cmd = [tbin, tex_path.name]
|
| 499 |
logs.append("▶ Compiling with tectonic …")
|