From 605884ed471a4ecd3aad9c89e7a731099c4aed5b Mon Sep 17 00:00:00 2001 From: mar77i Date: Wed, 9 Jul 2025 00:01:38 +0200 Subject: [PATCH] simplify launcher with softlinks --- bookpaint.py | 7 +--- launch.py | 93 ++++++++++++++++++++++++++++++++++++++++++++++ launch/__init__.py | 77 -------------------------------------- rps.py | 7 +--- zenbook_conf.py | 7 +--- 5 files changed, 96 insertions(+), 95 deletions(-) mode change 100755 => 120000 bookpaint.py create mode 100755 launch.py delete mode 100644 launch/__init__.py mode change 100755 => 120000 rps.py mode change 100755 => 120000 zenbook_conf.py diff --git a/bookpaint.py b/bookpaint.py deleted file mode 100755 index 39415ea..0000000 --- a/bookpaint.py +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python3 - -from launch import run - -if __name__ == "__main__": - run() diff --git a/bookpaint.py b/bookpaint.py new file mode 120000 index 0000000..a0e149e --- /dev/null +++ b/bookpaint.py @@ -0,0 +1 @@ +launch.py \ No newline at end of file diff --git a/launch.py b/launch.py new file mode 100755 index 0000000..01a7c8e --- /dev/null +++ b/launch.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python3 + +import os +import shlex +import sys +from argparse import ArgumentParser +from contextlib import redirect_stdout +from importlib import import_module +from io import StringIO +from pathlib import Path +from shutil import rmtree +from time import time + + +def setup_venv(): + venv_dir = (Path(__file__).parent / "venv").absolute() + install_venv = True + if venv_dir.is_dir(): + for p in ( + venv_dir, + *( + base / ent + for base, dirs, files in venv_dir.walk() + for ent in (*dirs, *files) + ) + ): + if p.stat().st_mtime >= time() - 86400: + install_venv = False + break + else: + if venv_dir.exists(): + rmtree(venv_dir) + assert not venv_dir.exists() + os.system(shlex.join((sys.executable, "-m", "venv", str(venv_dir)))) + new_env = {"VIRTUAL_ENV": str(venv_dir)} + venv_bin_str = str(venv_dir / "bin") + if venv_bin_str not in os.environ['PATH'].split(os.pathsep): + new_env["PATH"] = f"{venv_bin_str}{os.pathsep}{os.environ['PATH']}" + os.environ.update(new_env) + if install_venv: + os.system( + shlex.join( + ( + Path(sys.executable).name, + "-m", + "pip", + "install", + "-qU", + "pip", + "pygame", + ) + ) + ) + venv_dir.touch(0o755, True) + os.execl(sys.executable, Path(sys.executable).name, *sys.argv) + exit(1) + + +def find_root(module_name, module_globals): + from ui import Root + + for key, value in module_globals.items(): + if key.startswith("__") and key.endswith("__"): + continue + if value is not Root and isinstance(value, type) and issubclass(value, Root): + value().run() + break + else: + raise ValueError(f"Module not found: {module_name}") + return + + +def main(): + try: + with redirect_stdout(StringIO()): + # ruff: noqa: F401 + import pygame # type: ignore + except ImportError: + setup_venv() + raise + + ap = ArgumentParser() + ap.add_argument("--module", "-m") + args = ap.parse_args() + module_name = Path(args.module or sys.argv[0]).stem + find_root( + module_name, + import_module(f"{module_name}.{module_name}", module_name).__dict__, + ) + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/launch/__init__.py b/launch/__init__.py deleted file mode 100644 index 8f59c15..0000000 --- a/launch/__init__.py +++ /dev/null @@ -1,77 +0,0 @@ -import os -import shlex -import sys -from contextlib import redirect_stdout -from importlib import import_module -from inspect import stack -from io import StringIO -from pathlib import Path -from time import time - - -def setup_venv(): - venv_dir = (Path(__file__).parents[1] / "venv").absolute() - if venv_dir.is_dir(): - install_venv = max( - p.stat().st_mtime - for p in ( - venv_dir, - *( - base / ent - for base, dirs, files in venv_dir.walk() - for ent in (*dirs, *files) - ) - ) - ) < time() - 86400 - else: - if venv_dir.exists(): - venv_dir.unlink() - assert not venv_dir.exists() - os.system(shlex.join((sys.executable, "-m", "venv", str(venv_dir)))) - install_venv = True - new_env = {"VIRTUAL_ENV": str(venv_dir)} - venv_bin_str = str(venv_dir / "bin") - if venv_bin_str not in os.environ['PATH'].split(os.pathsep): - new_env["PATH"] = f"{venv_bin_str}{os.pathsep}{os.environ['PATH']}" - os.environ.update(new_env) - if install_venv: - os.system("python -m pip install -qU pip") - os.system("python -m pip install -qU pygame") - venv_dir.touch(0o755, True) - os.execl(sys.executable, Path(sys.executable).name, *sys.argv) - exit(1) - - -try: - with redirect_stdout(StringIO()): - # ruff: noqa: F401 - import pygame # type: ignore -except ImportError: - setup_venv() - raise - - -def find_root(module_globals): - from ui import Root - - for key, value in module_globals.items(): - if key.startswith("__") and key.endswith("__"): - continue - if value is not Root and isinstance(value, type) and issubclass(value, Root): - return value - return None - - -def run(): - for fi in stack(): - caller_name = fi.frame.f_globals["__name__"] - if caller_name == "__main__" or caller_name.endswith(".__main__"): - module_globals = fi.frame.f_globals - break - else: - raise ValueError("Could not determine caller name") - root_class = find_root(module_globals) - if root_class is None: - package = Path(module_globals["__file__"]).stem - root_class = find_root(import_module(f"{package}.{package}").__dict__) - root_class().run() diff --git a/rps.py b/rps.py deleted file mode 100755 index 39415ea..0000000 --- a/rps.py +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python3 - -from launch import run - -if __name__ == "__main__": - run() diff --git a/rps.py b/rps.py new file mode 120000 index 0000000..a0e149e --- /dev/null +++ b/rps.py @@ -0,0 +1 @@ +launch.py \ No newline at end of file diff --git a/zenbook_conf.py b/zenbook_conf.py deleted file mode 100755 index 39415ea..0000000 --- a/zenbook_conf.py +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python3 - -from launch import run - -if __name__ == "__main__": - run() diff --git a/zenbook_conf.py b/zenbook_conf.py new file mode 120000 index 0000000..a0e149e --- /dev/null +++ b/zenbook_conf.py @@ -0,0 +1 @@ +launch.py \ No newline at end of file -- 2.51.0