fuck you all
This commit is contained in:
118
problem_scanner.py
Normal file
118
problem_scanner.py
Normal file
@@ -0,0 +1,118 @@
|
||||
import os
|
||||
import time
|
||||
import json
|
||||
import sqlite3
|
||||
import threading
|
||||
import random
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
try:
|
||||
from watchdog.observers import Observer
|
||||
from watchdog.events import FileSystemEventHandler
|
||||
WATCHDOG_AVAILABLE = True
|
||||
except ImportError:
|
||||
WATCHDOG_AVAILABLE = False
|
||||
|
||||
PROBLEMS_DIR = Path(__file__).parent / 'problems'
|
||||
DB_PATH = Path(__file__).parent / 'problems.sqlite3'
|
||||
|
||||
class ProblemScannerThread(threading.Thread):
|
||||
def __init__(self, scan_interval=2):
|
||||
super().__init__(daemon=True)
|
||||
self.scan_interval = scan_interval
|
||||
self.last_state = {}
|
||||
self.observer = None
|
||||
|
||||
def create_table(self, conn):
|
||||
c = conn.cursor()
|
||||
c.execute('PRAGMA journal_mode=WAL;')
|
||||
c.execute('''CREATE TABLE IF NOT EXISTS problems (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
folder TEXT,
|
||||
description TEXT,
|
||||
test_code TEXT
|
||||
)''')
|
||||
conn.commit()
|
||||
|
||||
def scan(self):
|
||||
problems = []
|
||||
for folder in PROBLEMS_DIR.iterdir():
|
||||
if folder.is_dir():
|
||||
# Dynamically find manifest file (manifest.json or manifets.json)
|
||||
manifest_path = None
|
||||
for candidate in ["manifest.json", "manifets.json"]:
|
||||
candidate_path = folder / candidate
|
||||
if candidate_path.exists():
|
||||
manifest_path = candidate_path
|
||||
break
|
||||
desc_path = folder / 'description.md'
|
||||
test_path = folder / 'test.py'
|
||||
if manifest_path and test_path.exists():
|
||||
with open(desc_path, 'r') as f:
|
||||
description = f.read()
|
||||
with open(test_path, 'r') as f:
|
||||
test_code = f.read()
|
||||
problems.append({
|
||||
'folder': folder.name,
|
||||
'description': description,
|
||||
'test_code': test_code
|
||||
})
|
||||
return problems
|
||||
|
||||
def update_db(self, problems, retries=5):
|
||||
for attempt in range(retries):
|
||||
try:
|
||||
conn = sqlite3.connect(DB_PATH, timeout=2)
|
||||
c = conn.cursor()
|
||||
c.execute('PRAGMA journal_mode=WAL;')
|
||||
c.execute('DELETE FROM problems')
|
||||
for p in problems:
|
||||
c.execute('INSERT INTO problems (folder, description, test_code) VALUES (?, ?, ?)',
|
||||
(p['folder'], p['description'], p['test_code']))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
return
|
||||
except sqlite3.OperationalError as e:
|
||||
if 'locked' in str(e):
|
||||
time.sleep(0.2 + random.random() * 0.3)
|
||||
else:
|
||||
raise
|
||||
print('Failed to update problems DB after several retries due to lock.')
|
||||
|
||||
def rescan_and_update(self):
|
||||
problems = self.scan()
|
||||
self.update_db(problems)
|
||||
|
||||
def run(self):
|
||||
# Initial scan and table creation
|
||||
conn = sqlite3.connect(DB_PATH)
|
||||
self.create_table(conn)
|
||||
conn.close()
|
||||
self.rescan_and_update()
|
||||
if WATCHDOG_AVAILABLE:
|
||||
class Handler(FileSystemEventHandler):
|
||||
def __init__(self, scanner):
|
||||
self.scanner = scanner
|
||||
def on_any_event(self, event):
|
||||
self.scanner.rescan_and_update()
|
||||
event_handler = Handler(self)
|
||||
self.observer = Observer()
|
||||
self.observer.schedule(event_handler, str(PROBLEMS_DIR), recursive=True)
|
||||
self.observer.start()
|
||||
try:
|
||||
while True:
|
||||
time.sleep(1)
|
||||
finally:
|
||||
self.observer.stop()
|
||||
self.observer.join()
|
||||
else:
|
||||
# Fallback: poll every scan_interval seconds
|
||||
while True:
|
||||
time.sleep(self.scan_interval)
|
||||
self.rescan_and_update()
|
||||
|
||||
def start_problem_scanner():
|
||||
scanner = ProblemScannerThread()
|
||||
scanner.start()
|
||||
return scanner
|
||||
Reference in New Issue
Block a user