165 lines
5.0 KiB
Python
165 lines
5.0 KiB
Python
"""
|
|
Configuration Management for Scientific Gallery Generator
|
|
|
|
This module provides dataclasses for managing configuration, including
|
|
defaults for gallery generation settings.
|
|
"""
|
|
|
|
from dataclasses import dataclass, field
|
|
from pathlib import Path
|
|
from typing import List, Dict, Any, Union
|
|
import yaml
|
|
|
|
|
|
@dataclass
|
|
class GalleryDefaults:
|
|
"""Default values for gallery generation."""
|
|
png_dpi: int = 400
|
|
plot_root: str = "gallery"
|
|
cache_enabled: bool = True
|
|
inherit_from_parent: bool = True
|
|
|
|
|
|
@dataclass
|
|
class GallerySource:
|
|
"""Represents a single data source for the gallery."""
|
|
name: str
|
|
path: Union[str, Path]
|
|
|
|
def __post_init__(self):
|
|
"""Convert path to Path object if needed."""
|
|
if isinstance(self.path, str):
|
|
self.path = Path(self.path)
|
|
|
|
|
|
@dataclass
|
|
class GalleryConfig:
|
|
"""
|
|
Main configuration for gallery generation.
|
|
|
|
Can be created programmatically or loaded from YAML.
|
|
"""
|
|
web_folder: Union[str, Path]
|
|
sources: List[Union[GallerySource, Dict[str, Any]]] = field(
|
|
default_factory=list
|
|
)
|
|
png_dpi: int = GalleryDefaults.png_dpi
|
|
plot_root: str = GalleryDefaults.plot_root
|
|
cache_enabled: bool = GalleryDefaults.cache_enabled
|
|
inherit_from_parent: bool = GalleryDefaults.inherit_from_parent
|
|
backup_folder: str = ""
|
|
|
|
def __post_init__(self):
|
|
"""Normalize and validate configuration."""
|
|
# Convert web_folder to Path
|
|
if isinstance(self.web_folder, str):
|
|
self.web_folder = Path(self.web_folder)
|
|
|
|
# Convert sources to GallerySource objects if they're dicts
|
|
normalized_sources = []
|
|
for source in self.sources:
|
|
if isinstance(source, dict):
|
|
source = GallerySource(**source)
|
|
elif not isinstance(source, GallerySource):
|
|
raise TypeError(
|
|
f"Source must be dict or GallerySource, "
|
|
f"got {type(source)}"
|
|
)
|
|
normalized_sources.append(source)
|
|
self.sources = normalized_sources
|
|
|
|
@classmethod
|
|
def from_yaml(cls, yaml_file: Union[str, Path]) -> "GalleryConfig":
|
|
"""
|
|
Load configuration from a YAML file.
|
|
|
|
Args:
|
|
yaml_file: Path to the YAML configuration file
|
|
|
|
Returns:
|
|
GalleryConfig instance with loaded settings
|
|
|
|
Raises:
|
|
FileNotFoundError: If the YAML file doesn't exist
|
|
yaml.YAMLError: If the YAML file is malformed
|
|
"""
|
|
yaml_path = Path(yaml_file)
|
|
if not yaml_path.exists():
|
|
raise FileNotFoundError(f"Config file not found: {yaml_file}")
|
|
|
|
with open(yaml_path, "r") as f:
|
|
data = yaml.safe_load(f)
|
|
|
|
if data is None:
|
|
data = {}
|
|
|
|
# Extract relevant sections
|
|
web_folder = data.get("paths", {}).get("web_folder")
|
|
if not web_folder:
|
|
raise ValueError(
|
|
"web_folder must be specified in config under paths"
|
|
)
|
|
|
|
gallery_cfg = data.get("gallery", {})
|
|
sources_data = data.get("sources", [])
|
|
|
|
# Build sources list
|
|
sources = [
|
|
{"name": s["name"], "path": s["path"]} for s in sources_data
|
|
]
|
|
|
|
return cls(
|
|
web_folder=web_folder,
|
|
sources=sources,
|
|
png_dpi=gallery_cfg.get("png_dpi", GalleryDefaults.png_dpi),
|
|
plot_root=gallery_cfg.get(
|
|
"plot_root", GalleryDefaults.plot_root
|
|
),
|
|
cache_enabled=data.get("metadata", {}).get(
|
|
"cache_enabled", GalleryDefaults.cache_enabled
|
|
),
|
|
inherit_from_parent=data.get("metadata", {}).get(
|
|
"inherit_from_parent", GalleryDefaults.inherit_from_parent
|
|
),
|
|
backup_folder=gallery_cfg.get("backup_folder", ""),
|
|
)
|
|
|
|
def to_yaml(self, yaml_file: Union[str, Path]) -> 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
|
|
"""
|
|
yaml_path = Path(yaml_file)
|
|
|
|
data = {
|
|
"paths": {
|
|
"work_dir": str(Path.cwd()),
|
|
"web_folder": str(self.web_folder),
|
|
},
|
|
"gallery": {
|
|
"plot_root": self.plot_root,
|
|
"png_dpi": self.png_dpi,
|
|
"backup_folder": self.backup_folder,
|
|
},
|
|
"ui": {
|
|
"max_recent_plots": 20,
|
|
"search_debounce_ms": 300,
|
|
},
|
|
"metadata": {
|
|
"cache_enabled": self.cache_enabled,
|
|
"inherit_from_parent": self.inherit_from_parent,
|
|
"supported_formats": [".yaml", ".yml", ".json"],
|
|
},
|
|
"sources": [
|
|
{"name": s.name, "path": str(s.path)} for s in self.sources
|
|
],
|
|
}
|
|
|
|
with open(yaml_path, "w") as f:
|
|
yaml.dump(data, f, default_flow_style=False)
|