3b9d1ef1a8
- Replace the Docker build/publish CI stages with ruff (lint + format check), ty (type check), pip-audit, and pytest run directly against python:3.11-slim; Docker remains for manual/server deployment only. - Swap black/pylint/mypy for ruff/ty across pyproject.toml, and fix every resulting lint, format, and type diagnostic in gallery/ and plotstyle/. - Fix tests broken/stale from before the package restructuring: wrong `utils.*` import paths, mock patch targets pointed at the wrong module, and PDF-conversion tests still assuming ImageMagick instead of the current PyMuPDF-first path. Drop test_container.py (obsolete Docker-container smoke tests, fully superseded elsewhere). - Add a plain-venv + systemd --user timer deployment path (deploy/systemd/) for HPC login nodes without a Docker daemon, where public_html is already served by existing infrastructure. - Document both in CLAUDE.md, including running CI's checks locally before committing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
200 lines
6.2 KiB
Python
200 lines
6.2 KiB
Python
import json
|
|
|
|
import pytest
|
|
import yaml
|
|
|
|
from gallery.utils import metadata
|
|
|
|
|
|
def test_load_metadata_file_yaml(tmp_path):
|
|
data = {"a": 1, "b": "test"}
|
|
yaml_path = tmp_path / "meta.yaml"
|
|
yaml_path.write_text(yaml.dump(data))
|
|
result = metadata.load_metadata_file(yaml_path)
|
|
assert result == data
|
|
|
|
|
|
def test_load_metadata_file_json(tmp_path):
|
|
data = {"x": 42, "y": "hello"}
|
|
json_path = tmp_path / "meta.json"
|
|
json_path.write_text(json.dumps(data))
|
|
result = metadata.load_metadata_file(json_path)
|
|
assert result == data
|
|
|
|
|
|
def test_load_metadata_file_missing(tmp_path):
|
|
missing_path = tmp_path / "nope.yaml"
|
|
result = metadata.load_metadata_file(missing_path)
|
|
assert result == {}
|
|
|
|
|
|
def test_load_metadata_file_yml_extension(tmp_path):
|
|
data = {"test": "yml_format"}
|
|
yml_path = tmp_path / "meta.yml"
|
|
yml_path.write_text(yaml.dump(data))
|
|
result = metadata.load_metadata_file(yml_path)
|
|
assert result == data
|
|
|
|
|
|
def test_load_metadata_file_unknown_format(tmp_path):
|
|
txt_path = tmp_path / "meta.txt"
|
|
txt_path.write_text("some text")
|
|
result = metadata.load_metadata_file(txt_path)
|
|
assert result == {}
|
|
|
|
|
|
def test_load_metadata_file_malformed_yaml(tmp_path):
|
|
yaml_path = tmp_path / "bad.yaml"
|
|
yaml_path.write_text("invalid: yaml: content: [")
|
|
with pytest.raises(yaml.YAMLError):
|
|
metadata.load_metadata_file(yaml_path)
|
|
|
|
|
|
def test_load_metadata_file_malformed_json(tmp_path):
|
|
json_path = tmp_path / "bad.json"
|
|
json_path.write_text('{"invalid": json}')
|
|
with pytest.raises(json.JSONDecodeError):
|
|
metadata.load_metadata_file(json_path)
|
|
|
|
|
|
def test_load_folder_metadata_yaml(tmp_path):
|
|
data = {"folder": "metadata"}
|
|
metadata_path = tmp_path / "metadata.yaml"
|
|
metadata_path.write_text(yaml.dump(data))
|
|
result = metadata.load_folder_metadata(tmp_path)
|
|
assert result == data
|
|
|
|
|
|
def test_load_folder_metadata_yml(tmp_path):
|
|
data = {"folder": "metadata_yml"}
|
|
metadata_path = tmp_path / "metadata.yml"
|
|
metadata_path.write_text(yaml.dump(data))
|
|
result = metadata.load_folder_metadata(tmp_path)
|
|
assert result == data
|
|
|
|
|
|
def test_load_folder_metadata_json(tmp_path):
|
|
data = {"folder": "metadata_json"}
|
|
metadata_path = tmp_path / "metadata.json"
|
|
metadata_path.write_text(json.dumps(data))
|
|
result = metadata.load_folder_metadata(tmp_path)
|
|
assert result == data
|
|
|
|
|
|
def test_load_folder_metadata_missing(tmp_path):
|
|
result = metadata.load_folder_metadata(tmp_path)
|
|
assert result == {}
|
|
|
|
|
|
def test_get_metadata_file_path_existing_yaml(tmp_path):
|
|
metadata_path = tmp_path / "metadata.yaml"
|
|
metadata_path.write_text("test: data")
|
|
result = metadata.get_metadata_file_path(tmp_path)
|
|
assert result == str(metadata_path)
|
|
|
|
|
|
def test_get_metadata_file_path_existing_yml(tmp_path):
|
|
metadata_path = tmp_path / "metadata.yml"
|
|
metadata_path.write_text("test: data")
|
|
result = metadata.get_metadata_file_path(tmp_path)
|
|
assert result == str(metadata_path)
|
|
|
|
|
|
def test_get_metadata_file_path_existing_json(tmp_path):
|
|
metadata_path = tmp_path / "metadata.json"
|
|
metadata_path.write_text('{"test": "data"}')
|
|
result = metadata.get_metadata_file_path(tmp_path)
|
|
assert result == str(metadata_path)
|
|
|
|
|
|
def test_get_metadata_file_path_none_existing(tmp_path):
|
|
result = metadata.get_metadata_file_path(tmp_path)
|
|
expected = str(tmp_path / "metadata.yaml")
|
|
assert result == expected
|
|
|
|
|
|
def test_merge_metadata():
|
|
parent = {"project": "Test", "version": "1.0", "author": "Parent"}
|
|
child = {"experiment": "A", "version": "1.1"}
|
|
merged = metadata.merge_metadata(parent, child)
|
|
expected = {"project": "Test", "version": "1.1", "author": "Parent", "experiment": "A"}
|
|
assert merged == expected
|
|
|
|
|
|
def test_merge_metadata_empty_parent():
|
|
parent = {}
|
|
child = {"experiment": "A", "version": "1.1"}
|
|
merged = metadata.merge_metadata(parent, child)
|
|
assert merged == child
|
|
|
|
|
|
def test_merge_metadata_empty_child():
|
|
parent = {"project": "Test", "version": "1.0"}
|
|
child = {}
|
|
merged = metadata.merge_metadata(parent, child)
|
|
assert merged == parent
|
|
|
|
|
|
def test_resolve_metadata_for_plot_with_specific_yaml(tmp_path):
|
|
# Create plot-specific metadata file
|
|
plot_path = tmp_path / "test_plot.pdf"
|
|
plot_metadata_path = tmp_path / "test_plot.yaml"
|
|
plot_metadata = {"specific": "plot_data", "override": "plot_value"}
|
|
plot_metadata_path.write_text(yaml.dump(plot_metadata))
|
|
|
|
inherited = {"general": "data", "override": "inherited_value"}
|
|
result = metadata.resolve_metadata_for_plot(plot_path, inherited)
|
|
|
|
expected = {"general": "data", "override": "plot_value", "specific": "plot_data"}
|
|
assert result == expected
|
|
|
|
|
|
def test_resolve_metadata_for_plot_with_specific_json(tmp_path):
|
|
plot_path = tmp_path / "test_plot.pdf"
|
|
plot_metadata_path = tmp_path / "test_plot.json"
|
|
plot_metadata = {"specific": "plot_data_json"}
|
|
plot_metadata_path.write_text(json.dumps(plot_metadata))
|
|
|
|
inherited = {"general": "data"}
|
|
result = metadata.resolve_metadata_for_plot(plot_path, inherited)
|
|
|
|
expected = {"general": "data", "specific": "plot_data_json"}
|
|
assert result == expected
|
|
|
|
|
|
def test_resolve_metadata_for_plot_no_specific(tmp_path):
|
|
plot_path = tmp_path / "test_plot.pdf"
|
|
inherited = {"general": "data", "inherited": "value"}
|
|
result = metadata.resolve_metadata_for_plot(plot_path, inherited)
|
|
|
|
# Should return copy of inherited metadata
|
|
assert result == inherited
|
|
assert result is not inherited # Should be a copy
|
|
|
|
|
|
def test_save_metadata_cache(tmp_path):
|
|
cache_data = {"plot1": {"title": "Plot 1", "author": "Test"}, "plot2": {"title": "Plot 2", "experiment": "B"}}
|
|
|
|
metadata.save_metadata_cache(tmp_path, cache_data)
|
|
|
|
cache_file = tmp_path / "meta_cache.json"
|
|
assert cache_file.exists()
|
|
|
|
with cache_file.open("r") as f:
|
|
loaded_data = json.load(f)
|
|
|
|
assert loaded_data == cache_data
|
|
|
|
|
|
def test_save_metadata_cache_empty(tmp_path):
|
|
cache_data = {}
|
|
metadata.save_metadata_cache(tmp_path, cache_data)
|
|
|
|
cache_file = tmp_path / "meta_cache.json"
|
|
assert cache_file.exists()
|
|
|
|
with cache_file.open("r") as f:
|
|
loaded_data = json.load(f)
|
|
|
|
assert loaded_data == {}
|