fix: deterministic seed data — commit all 5 parquet files (LFS)
Browse filesThe Space only had enrollment+attendance parquet committed (.gitignore
excluded data/*.parquet), so seed_database() fell through to the Python
generator on EVERY request, and module-level random.seed() meant each
call produced different data (e.g. 1411 vs 1446 discipline rows).
- un-ignore data/*.parquet; commit all 5 via LFS, regenerated together
for cross-table consistency (verified byte-deterministic)
- app.py startup check now requires all 5 parquet files
- generate_seed_data() re-seeds the RNG per call as defense-in-depth
- .gitignore +0 -1
- app.py +4 -1
- data/attendance.parquet +0 -0
- data/discipline.parquet +3 -0
- data/enrollment.parquet +0 -0
- data/generate_seed.py +5 -0
- data/grades.parquet +3 -0
- data/students.parquet +3 -0
.gitignore
CHANGED
|
@@ -11,7 +11,6 @@ htmlcov/
|
|
| 11 |
build/
|
| 12 |
dist/
|
| 13 |
data/*.duckdb
|
| 14 |
-
data/*.parquet
|
| 15 |
|
| 16 |
# Git worktrees
|
| 17 |
.worktrees/
|
|
|
|
| 11 |
build/
|
| 12 |
dist/
|
| 13 |
data/*.duckdb
|
|
|
|
| 14 |
|
| 15 |
# Git worktrees
|
| 16 |
.worktrees/
|
app.py
CHANGED
|
@@ -28,7 +28,10 @@ print("🚀 Starting Kasualdad LFED...")
|
|
| 28 |
# Ensure Parquet seed files exist (generate on first boot, persist in /data/)
|
| 29 |
from pathlib import Path
|
| 30 |
_parquet_dirs = [Path("/data"), Path(__file__).parent / "data"]
|
| 31 |
-
_pq_files = [
|
|
|
|
|
|
|
|
|
|
| 32 |
_pq_found = any(
|
| 33 |
all((base / f).exists() for f in _pq_files)
|
| 34 |
for base in _parquet_dirs
|
|
|
|
| 28 |
# Ensure Parquet seed files exist (generate on first boot, persist in /data/)
|
| 29 |
from pathlib import Path
|
| 30 |
_parquet_dirs = [Path("/data"), Path(__file__).parent / "data"]
|
| 31 |
+
_pq_files = [
|
| 32 |
+
"enrollment.parquet", "attendance.parquet", "students.parquet",
|
| 33 |
+
"discipline.parquet", "grades.parquet",
|
| 34 |
+
]
|
| 35 |
_pq_found = any(
|
| 36 |
all((base / f).exists() for f in _pq_files)
|
| 37 |
for base in _parquet_dirs
|
data/attendance.parquet
CHANGED
|
Binary files a/data/attendance.parquet and b/data/attendance.parquet differ
|
|
|
data/discipline.parquet
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:94f24545806860637cba9c220f9bc7a0f1178cb84150d35e3196c95464579571
|
| 3 |
+
size 21710
|
data/enrollment.parquet
CHANGED
|
Binary files a/data/enrollment.parquet and b/data/enrollment.parquet differ
|
|
|
data/generate_seed.py
CHANGED
|
@@ -346,6 +346,11 @@ def generate_seed_data(conn: duckdb.DuckDBPyConnection) -> None:
|
|
| 346 |
- grades(student_id, school_name, school_year, grade_level, course_name,
|
| 347 |
term, letter_grade, grade_numeric, gpa)
|
| 348 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 349 |
# 1. Create tables
|
| 350 |
conn.execute("""
|
| 351 |
CREATE TABLE IF NOT EXISTS enrollment (
|
|
|
|
| 346 |
- grades(student_id, school_name, school_year, grade_level, course_name,
|
| 347 |
term, letter_grade, grade_numeric, gpa)
|
| 348 |
"""
|
| 349 |
+
# Re-seed on every call: module-level random.seed(SEED) only fixes the
|
| 350 |
+
# RNG once per process, so repeated calls (e.g. per-request fallback
|
| 351 |
+
# seeding) would otherwise produce different data each time.
|
| 352 |
+
random.seed(SEED)
|
| 353 |
+
|
| 354 |
# 1. Create tables
|
| 355 |
conn.execute("""
|
| 356 |
CREATE TABLE IF NOT EXISTS enrollment (
|
data/grades.parquet
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:ffe31388dc5f68e38e68c7471a3a6a7cbbaad816220c1b3a1122feb7a264077b
|
| 3 |
+
size 186893
|
data/students.parquet
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:9d1bd844bdc7afc398bb3e6440908000b37150a60a0b71333138820900f6ccb1
|
| 3 |
+
size 18179
|