74 lines
2.0 KiB
Python
74 lines
2.0 KiB
Python
from pathlib import Path
|
||
|
||
from config import STORAGE_DIR, PROJECTS_DIR, PROJECT_ROOT
|
||
|
||
THEMEN_DIR = STORAGE_DIR / "themen"
|
||
|
||
|
||
def _safe(name: str) -> str:
|
||
return name.replace("/", "_").replace("\x00", "")
|
||
|
||
|
||
def topic_dir(topic: str) -> Path:
|
||
return THEMEN_DIR / _safe(topic)
|
||
|
||
|
||
def arbeit_dir(topic: str) -> Path:
|
||
return topic_dir(topic) / "arbeit"
|
||
|
||
|
||
def bausteine_path(topic: str) -> Path:
|
||
return topic_dir(topic) / "bausteine.md"
|
||
|
||
|
||
def subbausteine_path(topic: str) -> Path:
|
||
"""Sidecar: pro Baustein die Subbausteine mit Stufe (von allen Guides geteilt)."""
|
||
return topic_dir(topic) / "subbausteine.json"
|
||
|
||
|
||
def frage_muster_path(topic: str) -> Path:
|
||
"""Sidecar: pro Baustein vordefinierte Frage-Muster (Subbaustein × Typ → Beispielfrage)."""
|
||
return topic_dir(topic) / "frage_muster.json"
|
||
|
||
|
||
def grafik_path(topic: str) -> Path:
|
||
"""Sidecar: pro Baustein eine Graph-Grafik (Knoten/Kanten), von allen Guides geteilt."""
|
||
return topic_dir(topic) / "grafik.json"
|
||
|
||
|
||
def quelle_path(topic: str) -> Path:
|
||
"""Persistierte Quellen-Wahl pro Thema: {type, ort, spec}."""
|
||
return topic_dir(topic) / "quelle.json"
|
||
|
||
|
||
def quelle_crawl_dir(topic: str) -> Path:
|
||
"""Zielordner für gecrawlte Link-Quellen (Seiten + PDF-.txt)."""
|
||
return topic_dir(topic) / "quelle"
|
||
|
||
|
||
def safe_ordner(ort: str) -> Path | None:
|
||
"""Ordnerpfad relativ zum Repo-Root, gesandboxt. None bei leer/Ausbruch (../, absolut außerhalb)."""
|
||
if not ort or not ort.strip():
|
||
return None
|
||
p = (PROJECT_ROOT / ort.strip()).resolve()
|
||
try:
|
||
p.relative_to(PROJECT_ROOT)
|
||
except ValueError:
|
||
return None
|
||
return p
|
||
|
||
|
||
def guide_content_path(topic: str, format_name: str) -> Path:
|
||
return topic_dir(topic) / "guides" / f"{format_name}.json"
|
||
|
||
|
||
def bausteine_topics() -> list[str]:
|
||
"""Themen, für die ein Themen-Ordner existiert."""
|
||
if not THEMEN_DIR.is_dir():
|
||
return []
|
||
return [d.name for d in THEMEN_DIR.iterdir() if d.is_dir()]
|
||
|
||
|
||
def project_dir(name: str) -> Path:
|
||
return PROJECTS_DIR / name
|