refactor: introduce REPO_ROOT in core.py, replace all CWD-relative paths

Defines REPO_ROOT = Path(__file__).parents[3] once in core.py.
Replaces Path(__file__).parent.parent...parent chains and Path("data/...")
CWD-relative references in admin/routes.py, content/__init__.py,
content/routes.py, and worker.py (4x local repo_root variables).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Deeman
2026-03-07 14:51:34 +01:00
parent 9f8afdbda7
commit c320bef83e
5 changed files with 24 additions and 16 deletions

View File

@@ -27,6 +27,7 @@ from quart import (
from ..auth.routes import role_required
from ..core import (
EMAIL_ADDRESSES,
REPO_ROOT,
config,
count_where,
csrf_protect,
@@ -2182,7 +2183,7 @@ async def scenario_pdf(scenario_id: int):
# Article Management
# =============================================================================
_ARTICLES_DIR = Path(__file__).parent.parent.parent.parent.parent / "data" / "content" / "articles"
_ARTICLES_DIR = REPO_ROOT / "content" / "articles"
_FRONTMATTER_RE = re.compile(r"^---\s*\n(.*?)\n---\s*\n", re.DOTALL)
@@ -2780,7 +2781,7 @@ async def article_new():
(build_dir / f"{article_slug}.html").write_text(body_html)
# Save markdown source
md_dir = Path("data/content/articles")
md_dir = REPO_ROOT / "content" / "articles"
md_dir.mkdir(parents=True, exist_ok=True)
(md_dir / f"{article_slug}.md").write_text(body)
@@ -2851,7 +2852,7 @@ async def article_edit(article_id: int):
build_dir.mkdir(parents=True, exist_ok=True)
(build_dir / f"{article['slug']}.html").write_text(body_html)
md_dir = Path("data/content/articles")
md_dir = REPO_ROOT / "content" / "articles"
md_dir.mkdir(parents=True, exist_ok=True)
(md_dir / f"{article['slug']}.md").write_text(body)
@@ -3042,7 +3043,7 @@ async def _rebuild_article(article_id: int):
)
else:
# Manual article: re-render from markdown file
md_path = Path("data/content/articles") / f"{article['slug']}.md"
md_path = REPO_ROOT / "content" / "articles" / f"{article['slug']}.md"
if not md_path.exists():
return
raw = md_path.read_text()

View File

@@ -17,14 +17,14 @@ import yaml
from jinja2 import ChainableUndefined, Environment
from ..analytics import fetch_analytics
from ..core import slugify, transaction, utcnow_iso
from ..core import REPO_ROOT, slugify, transaction, utcnow_iso
logger = logging.getLogger(__name__)
# ── Constants ────────────────────────────────────────────────────────────────
TEMPLATES_DIR = Path(__file__).parent / "templates"
BUILD_DIR = Path("data/content/_build")
BUILD_DIR = REPO_ROOT / "data" / "content" / "_build"
# Threshold functions per template slug.
# Return True → article should be noindex (insufficient data for quality content).

View File

@@ -9,7 +9,14 @@ from jinja2 import Environment, FileSystemLoader
from markupsafe import Markup
from quart import Blueprint, abort, g, redirect, render_template, request
from ..core import capture_waitlist_email, csrf_protect, feature_gate, fetch_all, fetch_one
from ..core import (
REPO_ROOT,
capture_waitlist_email,
csrf_protect,
feature_gate,
fetch_all,
fetch_one,
)
from ..i18n import get_translations
bp = Blueprint(
@@ -18,7 +25,7 @@ bp = Blueprint(
template_folder=str(Path(__file__).parent / "templates"),
)
BUILD_DIR = Path("data/content/_build")
BUILD_DIR = REPO_ROOT / "data" / "content" / "_build"
RESERVED_PREFIXES = (
"/admin", "/auth", "/planner", "/billing", "/dashboard",

View File

@@ -27,6 +27,9 @@ from quart import g, make_response, render_template, request, session # noqa: E
load_dotenv()
# Repo root: web/src/padelnomics/core.py → 4 levels up
REPO_ROOT = Path(__file__).parents[3]
def _env(key: str, default: str) -> str:
"""Get env var, treating empty string same as unset."""

View File

@@ -11,6 +11,7 @@ from datetime import datetime, timedelta
from .core import (
EMAIL_ADDRESSES,
REPO_ROOT,
config,
execute,
fetch_all,
@@ -710,9 +711,8 @@ async def handle_run_extraction(payload: dict) -> None:
If absent, runs all extractors via the umbrella `extract` entry point.
"""
import subprocess
from pathlib import Path
repo_root = Path(__file__).resolve().parents[4]
repo_root = REPO_ROOT
extractor = payload.get("extractor", "").strip()
if extractor:
cmd_name = f"extract-{extractor.replace('_', '-')}"
@@ -743,9 +743,8 @@ async def handle_run_transform(payload: dict) -> None:
2-hour absolute timeout — same as extraction.
"""
import subprocess
from pathlib import Path
repo_root = Path(__file__).resolve().parents[4]
repo_root = REPO_ROOT
result = await asyncio.to_thread(
subprocess.run,
["uv", "run", "sqlmesh", "-p", "transform/sqlmesh_padelnomics", "plan", "prod", "--auto-apply"],
@@ -769,9 +768,8 @@ async def handle_run_export(payload: dict) -> None:
10-minute absolute timeout.
"""
import subprocess
from pathlib import Path
repo_root = Path(__file__).resolve().parents[4]
repo_root = REPO_ROOT
result = await asyncio.to_thread(
subprocess.run,
["uv", "run", "python", "src/padelnomics/export_serving.py"],
@@ -791,9 +789,8 @@ async def handle_run_export(payload: dict) -> None:
async def handle_run_pipeline(payload: dict) -> None:
"""Run full ELT pipeline: extract → transform → export, stopping on first failure."""
import subprocess
from pathlib import Path
repo_root = Path(__file__).resolve().parents[4]
repo_root = REPO_ROOT
steps = [
(