Files
sunday/data_loader.py
2025-11-15 19:20:21 +10:00

122 lines
3.6 KiB
Python

"""
Comic data loader for YAML-based comic management.
This module scans the data/comics/ directory for .yaml files,
loads each comic's configuration, and builds the COMICS list.
"""
import yaml
from pathlib import Path
def load_comics_from_yaml(comics_dir='data/comics'):
"""
Load all comic data from YAML files in the specified directory.
Args:
comics_dir: Path to directory containing comic YAML files
Returns:
List of comic dictionaries, sorted by comic number
"""
comics = []
comics_path = Path(comics_dir)
if not comics_path.exists():
print(f"Warning: Comics directory '{comics_dir}' does not exist. Creating it...")
comics_path.mkdir(parents=True, exist_ok=True)
return []
# Find all .yaml and .yml files
yaml_files = list(comics_path.glob('*.yaml')) + list(comics_path.glob('*.yml'))
# Filter out template and README files
yaml_files = [f for f in yaml_files if f.stem.upper() not in ('TEMPLATE', 'README')]
if not yaml_files:
print(f"Warning: No YAML files found in '{comics_dir}'")
return []
for yaml_file in yaml_files:
try:
with open(yaml_file, 'r', encoding='utf-8') as f:
comic_data = yaml.safe_load(f)
if comic_data is None:
print(f"Warning: '{yaml_file.name}' is empty, skipping")
continue
if 'number' not in comic_data:
print(f"Warning: '{yaml_file.name}' missing required 'number' field, skipping")
continue
if 'filename' not in comic_data:
print(f"Warning: '{yaml_file.name}' missing required 'filename' field, skipping")
continue
if 'date' not in comic_data:
print(f"Warning: '{yaml_file.name}' missing required 'date' field, skipping")
continue
if 'alt_text' not in comic_data:
print(f"Warning: '{yaml_file.name}' missing required 'alt_text' field, skipping")
continue
comics.append(comic_data)
except yaml.YAMLError as e:
print(f"Error parsing '{yaml_file.name}': {e}")
continue
except Exception as e:
print(f"Error loading '{yaml_file.name}': {e}")
continue
# Sort by comic number
comics.sort(key=lambda c: c['number'])
return comics
def validate_comics(comics):
"""
Validate the loaded comics for common issues.
Args:
comics: List of comic dictionaries
Returns:
True if validation passes, False otherwise
"""
if not comics:
return True
numbers = [c['number'] for c in comics]
# Check for duplicate comic numbers
if len(numbers) != len(set(numbers)):
duplicates = [n for n in numbers if numbers.count(n) > 1]
print(f"Warning: Duplicate comic numbers found: {set(duplicates)}")
return False
# Check for gaps in comic numbering (optional warning)
for i in range(len(comics) - 1):
if comics[i+1]['number'] - comics[i]['number'] > 1:
print(f"Info: Gap in comic numbering between {comics[i]['number']} and {comics[i+1]['number']}")
return True
if __name__ == '__main__':
# Test the loader
print("Loading comics from data/comics/...")
comics = load_comics_from_yaml()
print(f"Loaded {len(comics)} comics")
if validate_comics(comics):
print("Validation passed!")
for comic in comics:
title = comic.get('title', f"#{comic['number']}")
print(f" - Comic {comic['number']}: {title} ({comic['date']})")
else:
print("Validation failed!")