#!/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 ") 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()