Rewrite CI to lint/typecheck/audit/test only; add HPC deployment path

- 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>
This commit is contained in:
2026-07-22 15:29:55 +02:00
parent 4ba321b327
commit 3b9d1ef1a8
27 changed files with 752 additions and 915 deletions
+6 -2
View File
@@ -3,6 +3,7 @@
from __future__ import annotations
import warnings
from typing import Optional
from matplotlib.axes import Axes
from matplotlib.colors import to_rgba
@@ -21,7 +22,7 @@ def style_legend(
ax: Axes,
loc: str = "outside right upper",
frameon: bool = False,
title: str = None,
title: Optional[str] = None,
**kwargs,
):
"""Add a figure-level legend, placed outside the axes by default.
@@ -43,12 +44,15 @@ def style_legend(
)
fig = ax.get_figure()
assert fig is not None, "ax must be attached to a figure"
handles = kwargs.pop("handles", None)
labels = kwargs.pop("labels", None)
if handles is None or labels is None:
handles, labels = ax.get_legend_handles_labels()
legend = fig.legend(handles, labels, loc=loc, frameon=frameon, title=title, **kwargs)
# matplotlib-stubs' `loc` Literal doesn't include the "outside ..." compound
# locations matplotlib actually supports at runtime (e.g. "outside right upper").
legend = fig.legend(handles, labels, loc=loc, frameon=frameon, title=title, **kwargs) # ty: ignore[invalid-argument-type]
if legend.get_title() is not None:
legend.get_title().set_fontweight("bold")
return legend
+6 -4
View File
@@ -5,8 +5,8 @@ from __future__ import annotations
from pathlib import Path
from typing import Mapping, Sequence, Union
import numpy as np
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.axes import Axes
from matplotlib.colorbar import Colorbar
from matplotlib.figure import Figure
@@ -53,8 +53,8 @@ def _set_figure_title(fig: Figure, title: Union[str, None], params: Union[Mappin
def new_figure(
preset: Union[str, tuple] = "thesis-single",
*,
title: str = None,
params: Mapping = None,
title: Union[str, None] = None,
params: Union[Mapping, None] = None,
**subplots_kwargs,
):
"""Create a figure/axes pair sized for a named preset or an explicit (w, h) tuple.
@@ -113,7 +113,9 @@ def colorbar(mappable, ax: Axes, size: str = "5%", pad: float = 0.05, **kwargs)
"""
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size=size, pad=pad)
cb = ax.get_figure().colorbar(mappable, cax=cax, **kwargs)
fig = ax.get_figure()
assert fig is not None, "ax must be attached to a figure"
cb = fig.colorbar(mappable, cax=cax, **kwargs)
# Colorbar draws its own border (a dedicated "outline" spine) that isn't
# covered by axes.spines.{left,right,top} — without this it'd pick up
# the bold black bottom-spine color/width from the main theme as a box
+2 -2
View File
@@ -20,10 +20,10 @@ exactly this reason.
from __future__ import annotations
from cycler import cycler
from importlib import resources
import matplotlib.pyplot as plt
from cycler import cycler
from .colors import CATEGORICAL
@@ -45,7 +45,7 @@ def use(cycle_linestyles: bool = False) -> None:
sequence, so series stay distinguishable even if color is lost
(grayscale printing, projector glare, color-vision deficiency).
"""
style_path = resources.files("plotstyle").joinpath("assets", "plotstyle.mplstyle")
style_path = resources.files("plotstyle").joinpath("assets").joinpath("plotstyle.mplstyle")
plt.style.use(str(style_path))
if cycle_linestyles: