Added libs

This commit is contained in:
Lucas
2026-01-25 13:55:46 +10:00
parent 575c682afc
commit f70af3c4ea
229 changed files with 26983 additions and 0 deletions

142
app/start.py Normal file
View File

@@ -0,0 +1,142 @@
import os
import sys
import logging
from logging.handlers import RotatingFileHandler
import shutil
import pathlib
import urllib.request
import subprocess
import zipfile
import venv
from pathlib import Path
# ==============================
# Configuration constants
# ==============================
ROOT_DIR = Path(__file__).parent.resolve()
LIBS_DIR = ROOT_DIR / "libs"
LOGS_DIR = ROOT_DIR / "logs"
APP_MAIN = LIBS_DIR / "app" / "main.py"
APP_ZIP = LIBS_DIR / "app.zip"
DEFAULT_REPOSITORY = "https://n0sys.duckdns.org/downloads/libs"
ARGS_LIST = ["updateApp=False", "updateLibs=True", "repack=True"]
# ==============================
# Logger setup
# ==============================
def setup_logger() -> logging.Logger:
"""Configure application logger with console and rotating file handlers."""
logger = logging.getLogger("start")
logger.setLevel(logging.DEBUG)
LOGS_DIR.mkdir(parents=True, exist_ok=True)
# Log format
formatter = logging.Formatter(
fmt="%(asctime)s | %(levelname)-8s | %(message)s",
datefmt="%Y-%m-%d %H:%M:%S"
)
# Console handler
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)
# File handler
file_handler = RotatingFileHandler(LOGS_DIR / "start.log", maxBytes=5_000_000, backupCount=3, encoding="utf-8")
file_handler.setLevel(logging.DEBUG)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
return logger
logger = setup_logger()
# ==============================
# Functions
# ==============================
def start_app():
"""Entry point for the launcher"""
logger.info("--------- START ---------")
logger.debug(f"Root path: {ROOT_DIR}")
LIBS_DIR.mkdir(parents=True, exist_ok=True)
# TODO: remove in production
# update_libs()
create_venv()
ensure_app()
# Import after app is available
from libs.app.common.process import new_python_process
from libs.app.common.args import read_kargs, kargs_to_array
args = kargs_to_array()
pid = new_python_process(APP_MAIN, str(get_venv_python()), args=args, wait=True, new_console=True)
logger.info(f"Main process running. PID {pid} - Args: {args}")
logger.info("--------- END ---------")
def get_venv_python():
"""Return the path to the venv's Python executable in a cross-platform way"""
if os.name == "nt":
return ROOT_DIR / ".venv" / "Scripts" / "python.exe"
else:
return ROOT_DIR / ".venv" / "bin" / "python"
def update_libs():
"""Development only: repack local libs"""
if ("updateApp=True" in ARGS_LIST or "updateLibs=True" in ARGS_LIST) and "repack=True" in ARGS_LIST:
update_version_script = r"C:\Workspace\utils\updateLibsVersion.py"
try:
subprocess.run(
[str(get_venv_python()), update_version_script],
cwd=ROOT_DIR,
creationflags=subprocess.CREATE_NEW_CONSOLE,
check=True,
)
except subprocess.CalledProcessError as e:
logger.error(f"Error running update libs: {e}")
def ensure_app():
"""Download, extract and install requirements of the application if not already present"""
if APP_MAIN.exists():
logger.debug("App already present, skipping download.")
return
url = f"{DEFAULT_REPOSITORY}/app/app.zip"
logger.info(f"Downloading app from {url} ...")
try:
urllib.request.urlretrieve(url, APP_ZIP)
except Exception as e:
logger.exception(f"Failed to download app")
raise
logger.info(f"Extracting {APP_ZIP}...")
with zipfile.ZipFile(APP_ZIP, 'r') as zip_ref:
zip_ref.extractall(LIBS_DIR)
logger.info(f"Installing app requirements ...")
python_exec = str(get_venv_python())
requirements_path = os.path.join(ROOT_DIR, "libs/app/requirements.txt")
subprocess.check_call([python_exec, "-m", "pip", "install", "-r", requirements_path])
def create_venv():
"""Ensure a local virtual environment exists."""
venv_dir = os.path.join(ROOT_DIR, ".venv")
if not os.path.exists(venv_dir):
logger.debug(f"Creating python venv: {venv_dir}")
venv.create(venv_dir, with_pip=True)
# ==============================
# Main
# ==============================
if __name__ == "__main__":
try:
start_app()
except Exception:
logger.exception("Error starting application")
sys.exit(1)