From 482b6415691f5978adafa872986cd421ddb73702 Mon Sep 17 00:00:00 2001 From: lwark Date: Mon, 30 Dec 2024 09:49:09 -0600 Subject: [PATCH] Debugging scripts import hell. --- src/submissions/__main__.py | 23 +---- src/submissions/tools/__init__.py | 91 ++++++++++++------- .../tools/scripts/backup_database.py | 4 +- src/submissions/tools/scripts/goodbye.py | 4 +- src/submissions/tools/scripts/hello.py | 4 +- src/submissions/tools/scripts/import_irida.py | 4 +- 6 files changed, 67 insertions(+), 63 deletions(-) diff --git a/src/submissions/__main__.py b/src/submissions/__main__.py index 32767b9..9f7fd7c 100644 --- a/src/submissions/__main__.py +++ b/src/submissions/__main__.py @@ -1,6 +1,5 @@ import sys, os -from tools import ctx, setup_logger, check_if_app, timer -from threading import Thread +from tools import ctx, setup_logger, check_if_app # environment variable must be set to enable qtwebengine in network path if check_if_app(): @@ -14,25 +13,9 @@ from PyQt6.QtWidgets import QApplication from frontend.widgets.app import App -@timer -def run_startup(): - for script in ctx.startup_scripts.values(): - logger.info(f"Running startup script: {script.__name__}") - thread = Thread(target=script, args=(ctx,)) - thread.start() - - -@timer -def run_teardown(): - for script in ctx.teardown_scripts.values(): - logger.info(f"Running teardown script: {script.__name__}") - thread = Thread(target=script, args=(ctx,)) - thread.start() - - if __name__ == '__main__': - run_startup() + ctx.run_startup() app = QApplication(['', '--no-sandbox']) ex = App(ctx=ctx) app.exec() - sys.exit(run_teardown()) + sys.exit(ctx.run_teardown()) diff --git a/src/submissions/tools/__init__.py b/src/submissions/tools/__init__.py index 94bcca0..4bff1e6 100644 --- a/src/submissions/tools/__init__.py +++ b/src/submissions/tools/__init__.py @@ -8,6 +8,8 @@ import time from datetime import date, datetime, timedelta from json import JSONDecodeError import logging, re, yaml, sys, os, stat, platform, getpass, inspect, json, numpy as np, pandas as pd +from threading import Thread + from dateutil.easter import easter from jinja2 import Environment, FileSystemLoader from logging import handlers @@ -239,6 +241,27 @@ def get_first_blank_df_row(df: pd.DataFrame) -> int: return df.shape[0] + 1 +def timer(func): + """ + Performs timing of wrapped function + + Args: + func (__function__): incoming function + + """ + + @wraps(func) + def wrapper(*args, **kwargs): + start_time = time.perf_counter() + value = func(*args, **kwargs) + end_time = time.perf_counter() + run_time = end_time - start_time + logger.debug(f"Finished {func.__name__}() in {run_time:.4f} secs") + return value + + return wrapper + + # Settings class Settings(BaseSettings, extra="allow"): @@ -421,7 +444,7 @@ class Settings(BaseSettings, extra="allow"): super().__init__(*args, **kwargs) self.set_from_db() - # self.set_startup_teardown() + self.set_scripts() # pprint(f"User settings:\n{self.__dict__}") def set_from_db(self): @@ -460,7 +483,38 @@ class Settings(BaseSettings, extra="allow"): p = Path(__file__).parent.joinpath("scripts").absolute() subs = [item.stem for item in p.glob("*.py") if "__" not in item.stem] for sub in subs: - importlib.import_module(f"tools.scripts.{sub}") + mod = importlib.import_module(f"tools.scripts.{sub}") + try: + func = mod.__getattribute__(sub) + except AttributeError: + try: + func = mod.__getattribute__("script") + except AttributeError: + continue + if sub in self.startup_scripts.keys(): + self.startup_scripts[sub] = func + if sub in self.teardown_scripts.keys(): + self.teardown_scripts[sub] = func + + @timer + def run_startup(self): + """ + Runs startup scripts. + """ + for script in self.startup_scripts.values(): + logger.info(f"Running startup script: {script.__name__}") + thread = Thread(target=script, args=(ctx,)) + thread.start() + + @timer + def run_teardown(self): + """ + Runs teardown scripts. + """ + for script in self.teardown_scripts.values(): + logger.info(f"Running teardown script: {script.__name__}") + thread = Thread(target=script, args=(ctx,)) + thread.start() @classmethod def get_alembic_db_path(cls, alembic_path, mode=Literal['path', 'schema', 'user', 'pass']) -> Path | str: @@ -1037,37 +1091,4 @@ def create_holidays_for_year(year: int | None = None) -> List[date]: return sorted(holidays) -def timer(func): - """ - Performs timing of wrapped function - - Args: - func (__function__): incoming function - - """ - - @wraps(func) - def wrapper(*args, **kwargs): - start_time = time.perf_counter() - value = func(*args, **kwargs) - end_time = time.perf_counter() - run_time = end_time - start_time - logger.debug(f"Finished {func.__name__}() in {run_time:.4f} secs") - return value - - return wrapper - - ctx = get_config(None) - - -def register_script(func): - """Register a function as a plug-in""" - if func.__name__ in ctx.startup_scripts.keys(): - ctx.startup_scripts[func.__name__] = func - if func.__name__ in ctx.teardown_scripts.keys(): - ctx.teardown_scripts[func.__name__] = func - return func - - -ctx.set_scripts() diff --git a/src/submissions/tools/scripts/backup_database.py b/src/submissions/tools/scripts/backup_database.py index b56c8e1..daa3cd5 100644 --- a/src/submissions/tools/scripts/backup_database.py +++ b/src/submissions/tools/scripts/backup_database.py @@ -5,11 +5,11 @@ import logging, shutil, pyodbc from datetime import date from pathlib import Path from tools import Settings -from .. import register_script +# from .. import register_script logger = logging.getLogger(f"submissions.{__name__}") -@register_script +# @register_script def backup_database(ctx: Settings): """ Copies the database into the backup directory the first time it is opened every month. diff --git a/src/submissions/tools/scripts/goodbye.py b/src/submissions/tools/scripts/goodbye.py index be5648b..c76d69e 100644 --- a/src/submissions/tools/scripts/goodbye.py +++ b/src/submissions/tools/scripts/goodbye.py @@ -2,8 +2,8 @@ Test script for teardown_scripts """ -from .. import register_script +# from .. import register_script -@register_script +# @register_script def goodbye(ctx): print("\n\nGoodbye. Thank you for using Robotics Submission Tracker.\n\n") diff --git a/src/submissions/tools/scripts/hello.py b/src/submissions/tools/scripts/hello.py index 2b162f2..5cbec2d 100644 --- a/src/submissions/tools/scripts/hello.py +++ b/src/submissions/tools/scripts/hello.py @@ -1,8 +1,8 @@ """ Test script for startup_scripts """ -from .. import register_script +# from .. import register_script -@register_script +# @register_script def hello(ctx): print("\n\nHello! Welcome to Robotics Submission Tracker.\n\n") diff --git a/src/submissions/tools/scripts/import_irida.py b/src/submissions/tools/scripts/import_irida.py index 1a75cf1..f3e8349 100644 --- a/src/submissions/tools/scripts/import_irida.py +++ b/src/submissions/tools/scripts/import_irida.py @@ -4,11 +4,11 @@ from datetime import datetime from tools import Settings from sqlalchemy.orm import Session -from .. import register_script +# from .. import register_script logger = logging.getLogger(f"submissions.{__name__}") -@register_script +# @register_script def import_irida(ctx: Settings): """ Grabs Irida controls from secondary database.