This commit is contained in:
onysd 2026-08-07 04:30:25 +03:00
parent d16f34070d
commit cf5a03ca89
3 changed files with 78 additions and 23 deletions

View file

@ -55,8 +55,8 @@ if defined PYTHON (
if not defined MISSING (set "MISSING=%%m") else (set "MISSING=!MISSING!, %%m")
)
if defined MISSING (
echo [WARN] Missing Python packages: !MISSING!
echo Install them with: !PYTHON! -m pip install -r tui-panel\requirements-panel.txt
echo [WARN] Missing or outdated Python packages: !MISSING!
echo Install them with: !PYTHON! -m pip install -U -r tui-panel\requirements-panel.txt
set "PROBLEMS=1"
) else (
echo [ok] Python dependencies OK ^(textual, psutil, cryptography^)

View file

@ -30,6 +30,18 @@ fi
# of launching real Python. Validate the version output too.
PYTHON=""
PYTHON_VERSION=""
# A local .venv/ (created per this script's own advice below, to install
# tui-panel/requirements-panel.txt without touching a Debian/Ubuntu
# system Python) takes priority over PATH -- once it exists, every later run
# should keep using it instead of silently falling back to an older/
# unrelated system interpreter.
if [[ -x ".venv/bin/python" ]]; then
if VER_OUT="$(.venv/bin/python --version 2>&1)" && [[ "$VER_OUT" == Python\ 3* ]]; then
PYTHON=".venv/bin/python"
PYTHON_VERSION="$VER_OUT"
fi
fi
if [[ -z "$PYTHON" ]]; then
for cand in python3 python; do
if command -v "$cand" >/dev/null 2>&1; then
if VER_OUT="$("$cand" --version 2>&1)" && [[ "$VER_OUT" == Python\ 3* ]]; then
@ -39,6 +51,7 @@ for cand in python3 python; do
fi
fi
done
fi
if [[ -z "$PYTHON" ]]; then
warn "Python 3 is not installed (needed to run the server-panel TUI)"
@ -52,8 +65,12 @@ fi
if [[ -n "$PYTHON" ]]; then
MISSING="$("$PYTHON" tui-panel/check_deps.py)"
if [[ -n "$MISSING" ]]; then
warn "Missing Python packages: $(echo "$MISSING" | tr '\n' ' ')"
echo " Install them with: $PYTHON -m pip install -r tui-panel/requirements-panel.txt"
warn "Missing or outdated Python packages: $(echo "$MISSING" | tr '\n' ' ')"
echo " Install them with: $PYTHON -m pip install -U -r tui-panel/requirements-panel.txt"
echo " On Debian/Ubuntu this usually fails with 'externally-managed-environment'"
echo " against the system Python -- use a venv instead, then just re-run this script"
echo " (it prefers .venv/ automatically once one exists):"
echo " python3 -m venv .venv && .venv/bin/pip install -r tui-panel/requirements-panel.txt"
PROBLEMS=1
else
ok "Python dependencies OK (textual, psutil, cryptography)"

View file

@ -1,35 +1,73 @@
#!/usr/bin/env python3
"""Reports which Python packages server-panel.py needs are missing.
"""Reports which Python packages server-panel.py needs are missing or too old.
Used by owpengram-server.sh / owpengram-server.bat before launching the
panel, so both launchers share one source of truth for the dependency list
instead of duplicating it in shell and batch syntax.
Prints one missing package's pip install name per line. Exit code is 0 if
everything is already installed, 1 if anything is missing.
A plain `importlib.import_module` presence check isn't enough: on Debian/
Ubuntu, `apt`'s python3-textual (and similar system packages) can be old
enough to import fine but lack symbols server-panel.py needs (e.g. the
`work` decorator, added well after the ancient version some distros still
ship) -- the import check passes, then the panel crashes with an
ImportError of its own a few lines into startup. Checking the installed
version against requirements-panel.txt's floor catches that upfront, with
the same actionable message as a genuinely missing package.
Prints one missing/outdated package's pip install spec per line. Exit code
is 0 if everything installed satisfies its minimum version, 1 otherwise.
"""
import importlib
import importlib.metadata
import sys
REQUIRED = [
("textual", "textual"),
("psutil", "psutil"),
("cryptography", "cryptography"),
("textual", "textual", "0.60"),
("psutil", "psutil", "5.9"),
("cryptography", "cryptography", "41.0"),
]
def _version_tuple(version: str) -> tuple[int, ...]:
"""Parses the leading dotted-numeric run of a version string.
Good enough for the plain "major.minor[.patch]" versions in
requirements-panel.txt and on PyPI -- not a full PEP 440 parser, but this
script only ever compares against floors from that one file.
"""
parts = []
for chunk in version.split("."):
digits = ""
for ch in chunk:
if not ch.isdigit():
break
digits += ch
parts.append(int(digits) if digits else 0)
return tuple(parts)
def main() -> int:
missing = []
for module_name, pip_name in REQUIRED:
problems = []
for module_name, pip_name, min_version in REQUIRED:
try:
importlib.import_module(module_name)
except ImportError:
missing.append(pip_name)
problems.append(f"{pip_name}>={min_version}")
continue
try:
installed = importlib.metadata.version(pip_name)
except importlib.metadata.PackageNotFoundError:
# Importable but no dist-info to check (unusual outside a system
# package with a broken/missing manifest) -- can't verify the
# version, so don't block on a guess either way.
continue
if _version_tuple(installed) < _version_tuple(min_version):
problems.append(f"{pip_name}>={min_version} (found {installed})")
for name in missing:
for name in problems:
print(name)
return 1 if missing else 0
return 1 if problems else 0
if __name__ == "__main__":