134 lines
3.6 KiB
Python

from __future__ import annotations
import sqlite3
from dataclasses import dataclass
from pathlib import Path
from typing import Iterable
@dataclass(frozen=True)
class DatabaseConfig:
db_path: Path
class DatabaseBootstrapper:
"""Creates the SQLite schema and demo data on demand."""
def __init__(self, config: DatabaseConfig) -> None:
self._config = config
@property
def path(self) -> Path:
return self._config.db_path
def initialize(self) -> None:
self._ensure_parent_dir()
with sqlite3.connect(self.path) as conn:
conn.execute("PRAGMA foreign_keys = ON")
self._create_tables(conn)
self._seed_demo_data(conn)
conn.commit()
def _ensure_parent_dir(self) -> None:
self.path.parent.mkdir(parents=True, exist_ok=True)
def _create_tables(self, conn: sqlite3.Connection) -> None:
conn.executescript(
"""
CREATE TABLE IF NOT EXISTS modules (
id TEXT PRIMARY KEY,
title TEXT NOT NULL,
credit_points INTEGER NOT NULL,
status TEXT NOT NULL,
progress_percent INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS exams (
id TEXT PRIMARY KEY,
module_id TEXT NOT NULL
REFERENCES modules(id) ON DELETE CASCADE,
title TEXT NOT NULL,
exam_date TEXT NOT NULL,
status TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS appointments (
id TEXT PRIMARY KEY,
title TEXT NOT NULL,
start_date TEXT NOT NULL,
description TEXT NOT NULL
);
"""
)
def _seed_demo_data(self, conn: sqlite3.Connection) -> None:
modules = [
(
"MAT101",
"Analysis I",
5,
"In Progress",
40,
),
(
"CS201",
"Algorithms",
6,
"Planned",
0,
),
(
"ENG150",
"Academic Writing",
3,
"Completed",
100,
),
]
exams = [
(
"EXAM-MAT101",
"MAT101",
"Klausur Analysis I",
"2025-12-15",
"Scheduled",
),
(
"EXAM-CS201",
"CS201",
"Algorithmik Projekt",
"2026-01-20",
"Planned",
),
]
appointments = [
(
"APPT-MENTOR",
"Mentoring",
"2025-12-08",
"Mentoring call via Teams",
),
(
"APPT-STUDY",
"Lerngruppe",
"2025-12-10",
"Gruppenlernen Bibliothek",
),
]
module_sql = "INSERT OR IGNORE INTO modules " "VALUES (?, ?, ?, ?, ?)"
exam_sql = "INSERT OR IGNORE INTO exams " "VALUES (?, ?, ?, ?, ?)"
appointment_sql = "INSERT OR IGNORE INTO appointments " "VALUES (?, ?, ?, ?)"
self._bulk_insert(conn, module_sql, modules)
self._bulk_insert(conn, exam_sql, exams)
self._bulk_insert(conn, appointment_sql, appointments)
def _bulk_insert(
self,
conn: sqlite3.Connection,
sql: str,
rows: Iterable[tuple],
) -> None:
conn.executemany(sql, rows)