Convert to proper python package
This commit is contained in:
+52
-199
@@ -1,130 +1,26 @@
|
||||
"""
|
||||
Scientific Gallery Generator
|
||||
Scientific Gallery Generator - Legacy CLI Entry Point
|
||||
|
||||
This module generates static HTML galleries from scientific plot collections.
|
||||
It converts PDF plots to PNG thumbnails, creates responsive web interfaces,
|
||||
and organizes plots into hierarchical directory structures.
|
||||
This module provides backward compatibility for the legacy CLI interface.
|
||||
For new development, use the gallery package API directly:
|
||||
|
||||
Features:
|
||||
- PDF to PNG conversion with configurable DPI
|
||||
- Incremental updates (only converts when source is newer)
|
||||
- Jinja2 templating for consistent HTML generation
|
||||
- Support for nested folder structures
|
||||
- Responsive grid layout with search and navigation
|
||||
from gallery import generate, GalleryConfig
|
||||
|
||||
config = GalleryConfig.from_yaml("config.yaml")
|
||||
generate(config, verbose=True)
|
||||
|
||||
Or use the new CLI:
|
||||
|
||||
gallery --config config.yaml --verbose
|
||||
"""
|
||||
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
from typing import Dict, Any, Optional
|
||||
from datetime import datetime
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
|
||||
from utils.config import Config, GalleryItem
|
||||
from utils.metadata import (
|
||||
load_folder_metadata,
|
||||
merge_metadata,
|
||||
save_metadata_cache,
|
||||
)
|
||||
from utils.processing import (
|
||||
process_plot_files,
|
||||
needs_update,
|
||||
render_gallery_page,
|
||||
)
|
||||
from gallery import generate
|
||||
from gallery.config import GalleryConfig
|
||||
|
||||
|
||||
CONFIG = Config.from_yaml("config.yaml")
|
||||
|
||||
|
||||
def datetime_from_timestamp(timestamp: float) -> datetime:
|
||||
"""Convert a Unix timestamp to a datetime object."""
|
||||
return datetime.fromtimestamp(timestamp)
|
||||
|
||||
|
||||
def strftime_filter(dt: datetime, fmt: str) -> str:
|
||||
"""Format a datetime object using strftime."""
|
||||
return dt.strftime(fmt)
|
||||
|
||||
|
||||
env = Environment(loader=FileSystemLoader("."))
|
||||
env.filters['datetime_from_timestamp'] = datetime_from_timestamp
|
||||
env.filters['strftime'] = strftime_filter
|
||||
template = env.get_template("templates/gallery.html")
|
||||
|
||||
|
||||
def build_gallery(
|
||||
source_dir: Path,
|
||||
web_dir: Path,
|
||||
relative_path: Path = None,
|
||||
inherited_metadata: Optional[Dict[str, Any]] = None,
|
||||
) -> None:
|
||||
def main(clean_first: bool = False, source_override: str = None) -> None:
|
||||
"""
|
||||
Recursively build gallery structure from source directory.
|
||||
|
||||
Processes all PDF files in the source directory, converts them to PNG,
|
||||
copies both to the web directory, and generates index.html files with
|
||||
navigation and thumbnails. Now includes metadata support.
|
||||
|
||||
Args:
|
||||
source_dir: Source directory containing PDF files
|
||||
web_dir: Target web directory for gallery output
|
||||
relative_path: Relative path from gallery root (for navigation)
|
||||
inherited_metadata: Metadata inherited from parent directories
|
||||
"""
|
||||
if relative_path is None:
|
||||
relative_path = Path(".")
|
||||
|
||||
if inherited_metadata is None:
|
||||
inherited_metadata = {}
|
||||
|
||||
folder_metadata = load_folder_metadata(source_dir)
|
||||
current_metadata = merge_metadata(inherited_metadata, folder_metadata)
|
||||
|
||||
# Find all plot files (both PDF and HTML)
|
||||
pdf_files = list(source_dir.glob("*.pdf"))
|
||||
html_files = list(source_dir.glob("*.html"))
|
||||
plot_files = pdf_files + html_files
|
||||
|
||||
items = []
|
||||
plot_metadata_cache = {}
|
||||
|
||||
# Process all plot files (PDFs and HTMLs)
|
||||
for plot_file in plot_files:
|
||||
item = process_plot_files(
|
||||
CONFIG=CONFIG,
|
||||
plot_file=plot_file,
|
||||
web_dir=web_dir,
|
||||
current_metadata=current_metadata,
|
||||
)
|
||||
items.append(item)
|
||||
plot_metadata_cache[plot_file.stem] = item["metadata"]
|
||||
|
||||
save_metadata_cache(web_dir, plot_metadata_cache)
|
||||
|
||||
subdirs = [d for d in source_dir.iterdir() if d.is_dir()]
|
||||
subdir_names = []
|
||||
for subdir in subdirs:
|
||||
subdir_web = web_dir / subdir.name
|
||||
subdir_web.mkdir(exist_ok=True)
|
||||
subdir_relative = relative_path / subdir.name
|
||||
build_gallery(subdir, subdir_web, subdir_relative, current_metadata)
|
||||
subdir_names.append(subdir.name)
|
||||
|
||||
render_gallery_page(
|
||||
CONFIG=CONFIG,
|
||||
template=template,
|
||||
web_dir=web_dir,
|
||||
items=items,
|
||||
subdirs=subdir_names,
|
||||
relative_path=relative_path,
|
||||
metadata=current_metadata
|
||||
)
|
||||
|
||||
|
||||
def main(
|
||||
clean_first: bool = False, source_override: Optional[str] = None
|
||||
) -> None:
|
||||
"""
|
||||
Main entry point for gallery generation.
|
||||
Main entry point for gallery generation (legacy interface).
|
||||
|
||||
Args:
|
||||
clean_first: If True, removes and recreates the gallery directory
|
||||
@@ -134,93 +30,50 @@ def main(
|
||||
Processes all configured sources and generates the complete gallery
|
||||
structure in the web directory. Ensures assets are available.
|
||||
"""
|
||||
gallery_root = Path(CONFIG.web_folder) / CONFIG.plot_root
|
||||
try:
|
||||
# Load configuration from config.yaml
|
||||
config = GalleryConfig.from_yaml("config.yaml")
|
||||
|
||||
if clean_first and gallery_root.exists():
|
||||
print(f"Cleaning gallery directory {gallery_root}...")
|
||||
shutil.rmtree(gallery_root)
|
||||
# Handle source override
|
||||
if source_override:
|
||||
from pathlib import Path
|
||||
from gallery.config import GallerySource
|
||||
|
||||
gallery_root.mkdir(parents=True, exist_ok=True)
|
||||
assets_src = Path("assets")
|
||||
assets_dst = gallery_root.parent / "assets"
|
||||
source_path = Path(source_override).resolve()
|
||||
|
||||
if assets_src.exists():
|
||||
main_css_src = assets_src / "css" / "main.css"
|
||||
main_css_dst = assets_dst / "css" / "main.css"
|
||||
if not assets_dst.exists() or needs_update(main_css_src, main_css_dst):
|
||||
if assets_dst.exists():
|
||||
shutil.rmtree(assets_dst)
|
||||
shutil.copytree(assets_src, assets_dst)
|
||||
print(f"Updated assets from {assets_src} to {assets_dst}")
|
||||
else:
|
||||
print(f"Warning: Assets directory {assets_src} not found")
|
||||
# Check if source is in config
|
||||
matching_source = None
|
||||
for source in config.sources:
|
||||
if Path(source.path).resolve() == source_path:
|
||||
matching_source = source
|
||||
break
|
||||
|
||||
# Determine which sources to process
|
||||
if source_override:
|
||||
source_path = Path(source_override).resolve()
|
||||
# If not in config, create a temporary source entry
|
||||
if matching_source is None:
|
||||
source_name = source_path.name
|
||||
print(
|
||||
f"Source {source_override} not in config. "
|
||||
f"Adding temporarily as '{source_name}'"
|
||||
)
|
||||
config.sources = [
|
||||
GallerySource(name=source_name, path=source_path)
|
||||
]
|
||||
else:
|
||||
config.sources = [matching_source]
|
||||
|
||||
# Check if source is in config
|
||||
matching_source = None
|
||||
for source in CONFIG.sources:
|
||||
if Path(source.path).resolve() == source_path:
|
||||
matching_source = source
|
||||
break
|
||||
# Generate gallery using the new API
|
||||
success = generate(
|
||||
config=config,
|
||||
clean_first=clean_first,
|
||||
verbose=True
|
||||
)
|
||||
|
||||
# If not in config, create a temporary source entry
|
||||
if matching_source is None:
|
||||
source_name = source_path.name
|
||||
msg = (
|
||||
f"Source {source_override} not in config. "
|
||||
f"Adding temporarily as '{source_name}'"
|
||||
)
|
||||
print(msg)
|
||||
matching_source = GalleryItem(name=source_name, path=source_path)
|
||||
if not success:
|
||||
exit(1)
|
||||
|
||||
sources_to_process = [matching_source]
|
||||
else:
|
||||
sources_to_process = CONFIG.sources
|
||||
|
||||
source_subdirs = []
|
||||
|
||||
for source in sources_to_process:
|
||||
source_path = Path(source.path)
|
||||
source_web_dir = gallery_root / source.name
|
||||
source_web_dir.mkdir(parents=True, exist_ok=True)
|
||||
source_subdirs.append(source.name)
|
||||
|
||||
if source_path.is_file() and source_path.suffix == '.pdf':
|
||||
item = process_plot_files(
|
||||
CONFIG=CONFIG,
|
||||
plot_file=source_path,
|
||||
web_dir=source_web_dir,
|
||||
)
|
||||
render_gallery_page(
|
||||
CONFIG=CONFIG,
|
||||
template=template,
|
||||
web_dir=source_web_dir,
|
||||
items=[item],
|
||||
subdirs=[],
|
||||
relative_path=Path(source.name)
|
||||
)
|
||||
elif source_path.is_dir():
|
||||
build_gallery(source_path, source_web_dir, Path(source.name))
|
||||
else:
|
||||
print(
|
||||
f"Warning: Source {source.path} is neither a "
|
||||
f"directory nor a PDF file. Skipping."
|
||||
)
|
||||
|
||||
print(f"Processed {source.name}: {source.path}")
|
||||
|
||||
render_gallery_page(
|
||||
CONFIG=CONFIG,
|
||||
template=template,
|
||||
web_dir=gallery_root,
|
||||
items=[],
|
||||
subdirs=source_subdirs,
|
||||
relative_path=Path("."),
|
||||
title="Gallery Root"
|
||||
)
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user