57 lines
1.9 KiB
Python
57 lines
1.9 KiB
Python
"""
|
||
data/roster_loader.py
|
||
Loads, cleans, and validates artist rosters from CSV files.
|
||
"""
|
||
|
||
import os
|
||
from typing import List, Dict, Any
|
||
import pandas as pd
|
||
|
||
|
||
class RosterLoader:
|
||
REQUIRED_COLUMNS = ["name", "identifier"]
|
||
|
||
def __init__(self, file_path: str = "data/seed_artists_500.csv"):
|
||
self.file_path = file_path
|
||
|
||
def load_roster(self) -> List[Dict[str, Any]]:
|
||
"""
|
||
Loads the CSV roster, validates columns, drops empty/duplicate rows,
|
||
and returns a clean list of artist dictionaries.
|
||
"""
|
||
if not os.path.exists(self.file_path):
|
||
raise FileNotFoundError(
|
||
f"Seed file '{self.file_path}' not found. Please verify the path."
|
||
)
|
||
|
||
df = pd.read_csv(self.file_path)
|
||
|
||
# Check for required schema columns
|
||
missing_cols = [c for c in self.REQUIRED_COLUMNS if c not in df.columns]
|
||
if missing_cols:
|
||
raise ValueError(
|
||
f"Seed CSV is missing required columns: {missing_cols}. "
|
||
f"Expected columns: {self.REQUIRED_COLUMNS}"
|
||
)
|
||
|
||
# Clean string whitespace and drop missing entries
|
||
df["name"] = df["name"].astype(str).str.strip()
|
||
df["identifier"] = df["identifier"].astype(str).str.strip()
|
||
|
||
df = df[
|
||
(df["name"] != "")
|
||
& (df["name"] != "nan")
|
||
& (df["identifier"] != "")
|
||
& (df["identifier"] != "nan")
|
||
]
|
||
|
||
# Drop duplicates by artist name (keep first occurrence)
|
||
initial_len = len(df)
|
||
df = df.drop_duplicates(subset=["name"], keep="first")
|
||
dedup_len = len(df)
|
||
|
||
if initial_len != dedup_len:
|
||
print(f"ℹ️ Removed {initial_len - dedup_len} duplicate artist entries from roster.")
|
||
|
||
print(f"📋 Successfully loaded {len(df)} validated artists from '{self.file_path}'.")
|
||
return df.to_dict(orient="records") |