""" Scientific Gallery Configuration Management This module provides dataclasses and utilities for managing configuration of the scientific gallery system, including paths, gallery settings, UI preferences, and data sources. """ from dataclasses import dataclass, field, asdict from pathlib import Path import yaml @dataclass class PathConfig: """Configuration for system paths and directories.""" work_dir: str web_folder: str cgi_script: str config_path: str @dataclass class GalleryConfig: """Configuration for gallery generation and display settings.""" plot_root: str png_dpi: int backup_folder: str @dataclass class UIConfig: """Configuration for user interface behavior and preferences.""" max_recent_plots: int search_debounce_ms: int @dataclass class MetadataConfig: """Configuration for metadata handling.""" cache_enabled: bool = True inherit_from_parent: bool = True supported_formats: list[str] = field( default_factory=lambda: ['.yaml', '.yml', '.json'] ) @dataclass class GalleryItem: """Represents a single data source for the gallery.""" name: str path: Path @dataclass class Config: """ Main configuration class that aggregates all gallery settings. Provides backward compatibility properties and methods for loading configuration from YAML files. """ paths: PathConfig gallery: GalleryConfig ui: UIConfig metadata: MetadataConfig sources: list[GalleryItem] = field(default_factory=list) @property def web_folder(self): """Backward compatibility property for web folder path.""" return self.paths.web_folder @property def png_dpi(self): """Backward compatibility property for PNG conversion DPI.""" return self.gallery.png_dpi @property def plot_root(self): """Backward compatibility property for plot root directory.""" return self.gallery.plot_root @property def backup_folder(self): """Backward compatibility property for backup folder path.""" return self.gallery.backup_folder @classmethod def from_yaml(cls, yaml_file: str) -> "Config": """ Load configuration from a YAML file. Args: yaml_file: Path to the YAML configuration file Returns: Config instance with loaded settings Raises: FileNotFoundError: If the YAML file doesn't exist yaml.YAMLError: If the YAML file is malformed """ with open(yaml_file, "r") as f: data = yaml.safe_load(f) paths_data = data.get('paths', {}) gallery_data = data.get('gallery', {}) ui_data = data.get('ui', {}) metadata_data = data.get('metadata', {}) sources_data = data.get('sources', []) paths = PathConfig(**paths_data) gallery = GalleryConfig(**gallery_data) ui = UIConfig(**ui_data) metadata = MetadataConfig(**metadata_data) sources = [ GalleryItem(name=source["name"], path=Path(source["path"])) for source in sources_data ] return cls( paths=paths, gallery=gallery, ui=ui, metadata=metadata, sources=sources ) def to_yaml(self, yaml_file: str) -> None: """ Save the current configuration to a YAML file. Args: yaml_file: Path where to save the YAML configuration Raises: IOError: If unable to write to the specified file """ with open(yaml_file, "w") as f: yaml.dump(asdict(self), f, default_flow_style=False) if __name__ == "__main__": config = Config.from_yaml("config.yaml") print("Loaded config successfully:", config)