Files
ETPlot/tests/validate_metadata.py
T
Kylian Schmidt 72ebc5e103 feat: Implement metadata system and reorganize project structure
 Features:
- Add comprehensive metadata system with YAML/JSON support
- Implement hierarchical metadata inheritance from parent folders
- Support plot-specific metadata overrides
- Add metadata caching for performance optimization

🗂️ Code Organization:
- Move Python orchestration code to orchestration/ folder
- Move validation utilities to tests/ folder
- Move documentation to docs/ folder
- Separate metadata functionality into dedicated module

🔧 Infrastructure:
- Add automatic asset copying to web directory
- Fix asset path resolution for nested directories
- Update template to use dynamic asset paths
- Add MetadataConfig class with inheritance options

📚 Documentation:
- Add comprehensive metadata usage guide (METADATA_USAGE.md)
- Add implementation documentation (METADATA_IMPLEMENTATION.md)
- Include example metadata files in examples/
- Add metadata validation utility script

🐛 Bug Fixes:
- Fix breadcrumb navigation and JavaScript functionality
- Resolve asset path issues in nested directories
- Update template imports for modular CSS/JS structure

This commit introduces a flexible metadata system that allows users to add
rich metadata to plots and folders using YAML or JSON files, with full
hierarchical inheritance and plot-specific overrides. The project structure
is now better organized with clear separation of concerns.
2025-07-08 12:33:49 +02:00

140 lines
3.9 KiB
Python

#!/usr/bin/env python3
"""
Metadata Validation Utility
This script validates metadata files in the gallery source directories,
checking for proper YAML/JSON syntax and common field validation.
"""
import sys
import json
import yaml
from pathlib import Path
from typing import Dict, Any, List
def validate_metadata_file(file_path: Path) -> tuple[bool, List[str]]:
"""
Validate a single metadata file.
Args:
file_path: Path to the metadata file
Returns:
Tuple of (is_valid, error_messages)
"""
errors = []
if not file_path.exists():
errors.append(f"File does not exist: {file_path}")
return False, errors
try:
with file_path.open('r', encoding='utf-8') as f:
suffix_lower = file_path.suffix.lower()
if suffix_lower in ['.yaml', '.yml']:
data = yaml.safe_load(f)
elif suffix_lower == '.json':
data = json.load(f)
else:
errors.append(f"Unsupported file format: {file_path}")
return False, errors
if data is None:
errors.append(f"Empty metadata file: {file_path}")
return False, errors
# Basic validation
if not isinstance(data, dict):
errors.append(f"Metadata must be a dictionary: {file_path}")
return False, errors
# Check for common issues
if 'title' in data and not isinstance(data['title'], str):
errors.append(f"Title must be a string: {file_path}")
if 'tags' in data and not isinstance(data['tags'], list):
errors.append(f"Tags must be a list: {file_path}")
if 'author' in data and not isinstance(data['author'], dict):
errors.append(f"Author must be a dictionary: {file_path}")
except (yaml.YAMLError, json.JSONDecodeError) as e:
errors.append(f"Parse error in {file_path}: {e}")
return False, errors
except Exception as e:
errors.append(f"Unexpected error reading {file_path}: {e}")
return False, errors
return len(errors) == 0, errors
def find_metadata_files(root_dir: Path) -> List[Path]:
"""
Find all metadata files in a directory tree.
Args:
root_dir: Root directory to search
Returns:
List of metadata file paths
"""
metadata_files = []
for pattern in ['**/*.yaml', '**/*.yml', '**/*.json']:
for file_path in root_dir.glob(pattern):
if file_path.name.startswith('meta.') or file_path.stem != file_path.name:
metadata_files.append(file_path)
return metadata_files
def main():
"""Main validation function."""
if len(sys.argv) != 2:
print("Usage: python validate_metadata.py <directory>")
sys.exit(1)
root_dir = Path(sys.argv[1])
if not root_dir.exists():
print(f"Error: Directory does not exist: {root_dir}")
sys.exit(1)
if not root_dir.is_dir():
print(f"Error: Not a directory: {root_dir}")
sys.exit(1)
print(f"Validating metadata files in: {root_dir}")
print("-" * 50)
metadata_files = find_metadata_files(root_dir)
if not metadata_files:
print("No metadata files found.")
return
total_files = len(metadata_files)
valid_files = 0
for file_path in metadata_files:
is_valid, errors = validate_metadata_file(file_path)
if is_valid:
print(f"{file_path.relative_to(root_dir)}")
valid_files += 1
else:
print(f"{file_path.relative_to(root_dir)}")
for error in errors:
print(f" - {error}")
print("-" * 50)
print(f"Summary: {valid_files}/{total_files} files valid")
if valid_files != total_files:
sys.exit(1)
if __name__ == "__main__":
main()