commit
Deploy production / deploy (push) Successful in 15s

This commit is contained in:
2026-08-14 10:05:48 -07:00
parent 034c1b653e
commit 69f9cfea41
3 changed files with 111 additions and 20 deletions
+103 -1
View File
@@ -12,6 +12,7 @@ from pathlib import Path
import re
import shutil
import subprocess
import sys
import tempfile
import threading
from typing import Any
@@ -33,6 +34,104 @@ class ProjectEditorError(Exception):
"""An expected project-editor problem suitable for display to a user."""
def _python_has_lektor(executable: Path) -> bool:
if not executable.is_file():
return False
options: dict[str, Any] = {
"capture_output": True,
"text": True,
"timeout": 10,
"check": False,
}
if os.name == "nt":
options["creationflags"] = subprocess.CREATE_NO_WINDOW
try:
result = subprocess.run(
[str(executable), "-c", "import lektor, tkinter"],
**options,
)
except (OSError, subprocess.SubprocessError):
return False
return result.returncode == 0
def _find_lektor_python(site_root: Path) -> Path | None:
"""Locate a Python runtime that can import both Lektor and Tkinter."""
candidates: list[Path] = []
configured = os.environ.get("LABYRICORN_LEKTOR_PYTHON", "").strip()
if configured:
candidates.append(Path(configured).expanduser())
if os.name == "nt":
candidates.extend(
(
site_root / ".venv" / "Scripts" / "python.exe",
Path(os.environ.get("LOCALAPPDATA", ""))
/ "pipx"
/ "pipx"
/ "venvs"
/ "lektor"
/ "Scripts"
/ "python.exe",
Path.home()
/ ".local"
/ "pipx"
/ "venvs"
/ "lektor"
/ "Scripts"
/ "python.exe",
)
)
else:
candidates.extend(
(
site_root / ".venv" / "bin" / "python",
Path.home() / ".local" / "pipx" / "venvs" / "lektor" / "bin" / "python",
)
)
lektor_command = shutil.which("lektor")
if lektor_command:
candidates.append(
Path(lektor_command).resolve().parent
/ ("python.exe" if os.name == "nt" else "python")
)
seen: set[Path] = set()
for candidate in candidates:
candidate = candidate.resolve()
if candidate in seen:
continue
seen.add(candidate)
if _python_has_lektor(candidate):
return candidate
return None
def _relaunch_with_lektor(site_root: Path) -> bool:
try:
import lektor # noqa: F401
except ModuleNotFoundError:
pass
else:
return False
if os.environ.get("LABYRICORN_LEKTOR_RELAUNCHED") == "1":
return False
executable = _find_lektor_python(site_root)
if executable is None:
return False
gui_executable = executable
if os.name == "nt":
pythonw = executable.with_name("pythonw.exe")
if pythonw.is_file():
gui_executable = pythonw
child_environment = {**os.environ, "LABYRICORN_LEKTOR_RELAUNCHED": "1"}
subprocess.Popen(
[str(gui_executable), str(Path(__file__).resolve()), *sys.argv[1:]],
cwd=site_root,
env=child_environment,
)
return True
def _load_project_importer() -> Any:
try:
return importlib.import_module("project_sources")
@@ -691,8 +790,11 @@ def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--site-root", type=Path, default=Path(__file__).resolve().parents[1])
args = parser.parse_args()
site_root = args.site_root.resolve()
if _relaunch_with_lektor(site_root):
return 0
try:
run_gui(ProjectSourceRegistry(args.site_root))
run_gui(ProjectSourceRegistry(site_root))
except ProjectEditorError as exc:
parser.exit(1, f"project-editor: ERROR: {exc}\n")
return 0