md for database as it was fucked up in windows script

This commit is contained in:
2025-08-17 12:19:18 +02:00
parent b6ab591054
commit 8dd5fcbeb7
5 changed files with 556 additions and 543 deletions

View File

@@ -3,3 +3,5 @@ Flask-SQLAlchemy>=3.1
Markdown>=3.6 Markdown>=3.6
MarkupSafe>=2.1 MarkupSafe>=2.1
watchdog>=4.0 watchdog>=4.0
gunicorn>=23.0.0
waitress>=3.0.2

View File

@@ -1,17 +1,25 @@
u!/bin/bash #!/bin/bash
set -e # exit if any command fails set -e # exit if any command fails
# Ensure QPP/database directory exists # Ensure src/database directory exists
mkdir -p src/database mkdir -p src/database
# Create virtual environment if it doesn't exist
if [ ! -d "venv" ]; then
python -m venv venv python -m venv venv
fi
source venv/bin/activate source venv/bin/activate
# Upgrade pip and install dependencies
pip install --upgrade pip pip install --upgrade pip
pip install -r requirements.txt pip install -r requirements.txt
# Export environment variables
export FLASK_APP=src.app export FLASK_APP=src.app
export FLASK_ENV=production export FLASK_ENV=production
flask run --host=0.0.0.0 --port=5000 # Run with Gunicorn
echo "Starting Flask app with Gunicorn..."
exec gunicorn -w 4 -b 0.0.0.0:5000 src.app:app

View File

@@ -1 +1,3 @@
python -m flask --app .\src\app.py run --host=0.0.0.0 --port=5000 :: make db directory and then launch the server
md .\src\database
python -m waitress --listen=0.0.0.0:8000 src.app:app

View File

@@ -18,7 +18,7 @@ app = Flask(__name__)
BASE_DIR = Path(__file__).parent BASE_DIR = Path(__file__).parent
app.config['SQLALCHEMY_DATABASE_URI'] = f"sqlite:///{BASE_DIR / 'database' / 'db.sqlite3'}" app.config['SQLALCHEMY_DATABASE_URI'] = f"sqlite:///{BASE_DIR / 'database' / 'db.sqlite3'}"
print(f">>>>>>>>>>>>>>>>>>>>< Using database URI: {app.config['SQLALCHEMY_DATABASE_URI']}") print(f"[ INFO ] : Using database URI: {app.config['SQLALCHEMY_DATABASE_URI']}")
db.init_app(app) db.init_app(app)

View File

@@ -77,9 +77,9 @@ class ProblemScannerThread(threading.Thread):
'test_code': test_code, 'test_code': test_code,
'difficulty': difficulty 'difficulty': difficulty
}) })
print(f"Found problem: {folder.name} ; Difficulty: {difficulty}") print(f"[ INFO ]: Found problem: {folder.name} ; Difficulty: {difficulty}")
except Exception as e: except Exception as e:
print(f"Error reading problem files for {folder.name}: {e}") print(f"[ ERROR ]: Error reading problem files for {folder.name}: {e}")
else: else:
missing_files = [] missing_files = []
if not manifest_path: if not manifest_path:
@@ -88,9 +88,9 @@ class ProblemScannerThread(threading.Thread):
missing_files.append("description.md") missing_files.append("description.md")
if not test_path.exists(): if not test_path.exists():
missing_files.append("test.py") missing_files.append("test.py")
print(f"Skipping {folder.name}: missing {', '.join(missing_files)}") print(f"[ SKIP ]: Skipping {folder.name}: missing {', '.join(missing_files)}")
print(f"Total problems found: {len(problems)}") print(f"[ INFO ]: Total problems found: {len(problems)}")
return problems return problems
def update_db(self, problems, retries=5): def update_db(self, problems, retries=5):
@@ -111,7 +111,7 @@ class ProblemScannerThread(threading.Thread):
(p['folder'], p['description'], p['difficulty'], p['test_code'])) (p['folder'], p['description'], p['difficulty'], p['test_code']))
conn.commit() conn.commit()
print(f"Updated database with {len(problems)} problems") print(f"[ INFO ]: Updated database with {len(problems)} problems")
conn.close() conn.close()
return return
@@ -121,37 +121,37 @@ class ProblemScannerThread(threading.Thread):
print(f"Database locked, retrying in {wait_time:.2f}s (attempt {attempt + 1})") print(f"Database locked, retrying in {wait_time:.2f}s (attempt {attempt + 1})")
time.sleep(wait_time) time.sleep(wait_time)
else: else:
print(f"Database error: {e}") print(f"[ ERROR ]: Database error: {e}")
raise raise
except Exception as e: except Exception as e:
print(f"Unexpected error updating database: {e}") print(f"[ ERROR ]: Unexpected error updating database: {e}")
raise raise
print('Failed to update problems DB after several retries due to lock.') print('[ FATAL ERROR ]: Failed to update problems DB after several retries due to lock.')
def rescan_and_update(self): def rescan_and_update(self):
print("Scanning for problems...") print("[ INFO ]: Scanning for problems...")
problems = self.scan() problems = self.scan()
self.update_db(problems) self.update_db(problems)
def run(self): def run(self):
print("Starting problem scanner...") print("[ INFO ]: Starting problem scanner...")
# Initial scan and table creation # Initial scan and table creation
try: try:
conn = sqlite3.connect(DB_PATH) conn = sqlite3.connect(DB_PATH)
self.create_table(conn) self.create_table(conn)
conn.close() conn.close()
print("Database initialized") print("[ INFO ]: Database initialized")
except Exception as e: except Exception as e:
print(f"Failed to initialize database: {e}") print(f"[ FATAL ERROR ]: Failed to initialize database: {e}")
return return
# Initial scan # Initial scan
self.rescan_and_update() self.rescan_and_update()
if WATCHDOG_AVAILABLE: if WATCHDOG_AVAILABLE:
print("Using watchdog for file monitoring") print("[ INFO ]: Using watchdog for file monitoring")
class Handler(FileSystemEventHandler): class Handler(FileSystemEventHandler):
def __init__(self, scanner): def __init__(self, scanner):
@@ -163,7 +163,7 @@ class ProblemScannerThread(threading.Thread):
now = time.time() now = time.time()
if now - self.last_event_time > 1: # Wait at least 1 second between rescans if now - self.last_event_time > 1: # Wait at least 1 second between rescans
self.last_event_time = now self.last_event_time = now
print(f"File system event: {event.event_type} - {event.src_path}") print(f"[ FSINFO ]: File system event: {event.event_type} - {event.src_path}")
self.scanner.rescan_and_update() self.scanner.rescan_and_update()
event_handler = Handler(self) event_handler = Handler(self)
@@ -175,19 +175,19 @@ class ProblemScannerThread(threading.Thread):
while True: while True:
time.sleep(1) time.sleep(1)
except KeyboardInterrupt: except KeyboardInterrupt:
print("Stopping problem scanner...") print("[ KBINT_INFO ]: Stopping problem scanner...")
finally: finally:
self.observer.stop() self.observer.stop()
self.observer.join() self.observer.join()
else: else:
print(f"Watchdog not available, using polling every {self.scan_interval}s") print(f"[ WARNING ]: Watchdog not available, using polling every {self.scan_interval}s")
# Fallback: poll every scan_interval seconds # Fallback: poll every scan_interval seconds
try: try:
while True: while True:
time.sleep(self.scan_interval) time.sleep(self.scan_interval)
self.rescan_and_update() self.rescan_and_update()
except KeyboardInterrupt: except KeyboardInterrupt:
print("Stopping problem scanner...") print("[ KBINT_INFO ]: Stopping problem scanner...")
def start_problem_scanner(): def start_problem_scanner():
scanner = ProblemScannerThread() scanner = ProblemScannerThread()
@@ -198,14 +198,15 @@ def start_problem_scanner():
def load_problems_from_json(json_path): def load_problems_from_json(json_path):
"""Load problems from JSON file into Flask database""" """Load problems from JSON file into Flask database"""
if not os.path.exists(json_path): if not os.path.exists(json_path):
print(f"Problem JSON file not found: {json_path}") print(f"[ DEPRECATED_INFO ]: Problem JSON file not found: {json_path}")
print("[ SUGGESTION ]: If you dont have this do not worry. Use mainfest.json!")
return return
try: try:
with open(json_path, 'r', encoding='utf-8') as f: with open(json_path, 'r', encoding='utf-8') as f:
problems = json.load(f) problems = json.load(f)
except Exception as e: except Exception as e:
print(f"Error reading JSON file: {e}") print(f"[ ERROR ]: Error reading JSON file: {e}")
return return
# This assumes you have imported the necessary Flask/SQLAlchemy components # This assumes you have imported the necessary Flask/SQLAlchemy components
@@ -223,24 +224,24 @@ def load_problems_from_json(json_path):
with open(p['solution'], 'r', encoding='utf-8') as sf: with open(p['solution'], 'r', encoding='utf-8') as sf:
test_code = sf.read() test_code = sf.read()
except Exception as e: except Exception as e:
print(f"Error reading solution file for {p['title']}: {e}") print(f"[ FATAL ERROR ]: Error reading solution file for {p['title']}: {e}")
if existing: if existing:
existing.description = p['description'] existing.description = p['description']
existing.test_code = test_code existing.test_code = test_code
print(f"Updated problem: {p['title']}") print(f"[ INFO ]: Updated problem: {p['title']}")
else: else:
new_problem = Problem(title=p['title'], description=p['description'], test_code=test_code) new_problem = Problem(title=p['title'], description=p['description'], test_code=test_code)
db.session.add(new_problem) db.session.add(new_problem)
print(f"Added new problem: {p['title']}") print(f"[ SUCCESS ]: Added new problem: {p['title']}")
db.session.commit() db.session.commit()
print("Successfully updated problems from JSON") print("[ SUCCESS ]: Successfully updated problems from JSON")
except ImportError: except ImportError:
print("Flask models not available - skipping JSON load") print("[ FATAL IMPORT ERROR ]: Flask models not available - skipping JSON load @execptImportError")
except Exception as e: except Exception as e:
print(f"Error loading problems from JSON: {e}") print(f"[ ERROR ]: Error loading problems from JSON: {e}")
def schedule_problem_reload(app, json_path, interval_hours=10): def schedule_problem_reload(app, json_path, interval_hours=10):
"""Schedule periodic reloading of problems from JSON""" """Schedule periodic reloading of problems from JSON"""
@@ -251,7 +252,7 @@ def schedule_problem_reload(app, json_path, interval_hours=10):
load_problems_from_json(json_path) load_problems_from_json(json_path)
time.sleep(interval_hours * 3600) time.sleep(interval_hours * 3600)
except Exception as e: except Exception as e:
print(f"Error in problem reload loop: {e}") print(f"[ FATAL ERROR ]: Error in problem reload loop: {e}")
time.sleep(60) # Wait 1 minute before retrying time.sleep(60) # Wait 1 minute before retrying
t = threading.Thread(target=reload_loop, daemon=True) t = threading.Thread(target=reload_loop, daemon=True)
@@ -366,7 +367,7 @@ def run_code_against_tests(user_code, test_code, timeout=10):
try: try:
os.unlink(temp_file) os.unlink(temp_file)
except Exception as e: except Exception as e:
print(f"Warning: Could not delete temp file {temp_file}: {e}") print(f"[ FATAL WARNING ]: Could not delete temp file {temp_file}: {e}")
runtime = time.perf_counter() - start_time runtime = time.perf_counter() - start_time
@@ -377,7 +378,7 @@ def run_code_against_tests(user_code, test_code, timeout=10):
'error': error if not passed else None 'error': error if not passed else None
} }
print(f"Test execution result: passed={passed}, runtime={runtime:.3f}s") print(f"[ TEST RESULT ]: passed={passed}, runtime={runtime:.3f}s")
if error: if error:
print(f"Error: {error}") print(f"Error: {error}")