134 lines
3.6 KiB
Python
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)
|