From 087fed017a22e95e365ab61a23e60c42d9f02902 Mon Sep 17 00:00:00 2001 From: Mabe Date: Sat, 26 Sep 2026 16:21:44 -0700 Subject: [PATCH] Implement flag handling and migration status checks; refactor database test functions and update requirements --- cli.py | 8 ++++---- flags/__init__py | 0 flags/status.py | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ main.py | 30 ++++++++++++++++++++++------- requirements.txt | 4 +++- tests/db_test.py | 46 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 126 insertions(+), 12 deletions(-) create mode 100644 flags/__init__py create mode 100644 flags/status.py create mode 100644 tests/db_test.py diff --git a/cli.py b/cli.py index c687842..1cdd537 100644 --- a/cli.py +++ b/cli.py @@ -3,6 +3,7 @@ import logging import time import os import sys +from flags import status print("loading") @@ -129,7 +130,6 @@ def exit_programm(): print("") print("Disconnect DB") print("logout") - os.remove("migration_status.flag") print("shutting down") time.sleep(0.75) os.system('cls' if os.name == 'nt' else 'clear') @@ -178,7 +178,7 @@ def menu(): #The Terminal App Starts here -time.sleep(5) +time.sleep(2) print(r""" ## ## ########## ### ### ## ## @@ -187,8 +187,8 @@ print(r""" ## ## ## ## ## ## ## ## ## """) +while not status.get_migration(): + time.sleep(0.5) logging.info("Menu is starting") time.sleep(2.5) -while not os.path.exists("migration_status.flag"): - time.sleep(0.5) menu() diff --git a/flags/__init__py b/flags/__init__py new file mode 100644 index 0000000..e69de29 diff --git a/flags/status.py b/flags/status.py new file mode 100644 index 0000000..6e5fe25 --- /dev/null +++ b/flags/status.py @@ -0,0 +1,50 @@ +import threading +from watchdog.events import PatternMatchingEventHandler +from watchdog.observers import Observer +import os +import time + +FLAGS_DIR = os.path.dirname(os.path.abspath(__file__)) + + + +class FlagHandler(PatternMatchingEventHandler): + def __init__(self, shared_state, lock): + super().__init__(patterns=["*.flag"], ignore_directories=True) + self.shared_state = shared_state + self.lock = lock + + def on_created(self, event): + try: + with open(event.src_path, "r") as f: + content = f.read().strip() + except FileNotFoundError: + return + try: + os.remove(event.src_path) + except FileNotFoundError: + pass + with self.lock: + self.shared_state["current"] = content + time.sleep(2) + +shared_state = {"current": None} +lock = threading.Lock() + +observer = Observer() +observer.schedule(FlagHandler(shared_state, lock), path=FLAGS_DIR, recursive=False) +observer.start() + +def get_status(): + with lock: + current = shared_state["current"] + if current == "db_check_done": + return False + return current + +def get_migration(): + with lock: + current = shared_state["current"] + if current == "migration_done": + return True + return False \ No newline at end of file diff --git a/main.py b/main.py index 6cf689a..140b073 100644 --- a/main.py +++ b/main.py @@ -5,6 +5,7 @@ import os import auth.api_security as auth import time import threading +from tests import db_test try: os.remove("api.log") @@ -43,24 +44,39 @@ def run_migration(): ) process.wait() migration_done = (process.returncode == 0) - with open("migration_status.flag", "w") as f: - f.write("done" if migration_done else "failed") + with open("flags/migration_status.flag", "w") as f: + f.write("migration_done" if migration_done else "failed") -thread = threading.Thread(target=run_migration) -thread.start() + + +#DB test +def run_db_test(): + tokens = db_test.test_table("tokens", ["tokens", "time", "end_date"]) + user = db_test.test_table("user", ["username", "password", "role"]) + items = db_test.test_table("luggage", ["clothes", "weight", "pieces"]) + time.sleep(5) + if tokens == True & user == True & items == True: + with open("flags/db.flag", "w") as f: + f.write("db_check_done") + else: + os._exit(1) #cli and api log_file = open("api_server.log", "w", encoding="utf-8") api_process = subprocess.Popen( - ["fastapi", "dev", "api_server.py"], + ["fastapi", "dev", "api_server.py", "--reload-dir", "web", "--reload-dir", "api", "--reload-dir", "api_server.py",], stdout=log_file, stderr=log_file, env=env ) cli_process = subprocess.Popen([sys.executable, "cli.py"]) -api_process.wait() -cli_process.wait() +db_thread = threading.Thread(target=run_db_test) +db_thread.start() +thread = threading.Thread(target=run_migration) +thread.start() +threading.Thread(target=api_process.wait, daemon=True).start() +threading.Thread(target=cli_process.wait, daemon=True).start() # automatic durataion validation check while True: diff --git a/requirements.txt b/requirements.txt index 19b80e1..7304c74 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,4 +5,6 @@ Jinja2==3.1.6 MarkupSafe==3.0.3 itsdangerous==2.2.0 alembic==1.20.0 -SQLAlchemy==2.0.54 \ No newline at end of file +SQLAlchemy==2.0.54 +watchdog==6.0.0 +#watchfiles==1.2.0 \ No newline at end of file diff --git a/tests/db_test.py b/tests/db_test.py new file mode 100644 index 0000000..b6e49e7 --- /dev/null +++ b/tests/db_test.py @@ -0,0 +1,46 @@ +import sys +import os + +sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) + + + +import os +import db +import logging +import sys +from migration import alembic_scipt as alembic +from sqlalchemy import inspect + +session = db.session +engine = db.engine + +def test_column(engine, tablename, row): + try: + inspector = inspect(engine) + columns = [col["name"] for col in inspector.get_columns(tablename)] + return row in columns + except Exception as e: + logging.error(e) + + +def test_table(table, columns): + for column in columns: + try: + exists = test_column(engine, table, column) + if exists == False: + logging.error(f"DB has not all columns. {column} is missing") + print(f"Column {column} is missing") + sys.exit() + os._exit(1) + return False + else: + logging.info("Column fine") + except Exception as e: + logging.error(e) + return True + +def migration_check(): + if alembic.check_db() == False: + print("migrating") + logging.info("DB is migrating") \ No newline at end of file