From 5c72bfd86a692a8c3b3002bdc252ceecf586afec Mon Sep 17 00:00:00 2001 From: Matt Fisher Date: Tue, 2 Jun 2026 15:20:37 -0600 Subject: [PATCH 01/10] Drop support for Pythons 3.9-3.11 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Clément Robert <14075922+neutrinoceros@users.noreply.github.com> --- .github/workflows/check.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 6 +++--- README.rst | 2 +- environment.yml | 2 +- pyproject.toml | 8 ++++---- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 1336e17..cf0b6fc 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -10,7 +10,7 @@ jobs: runs-on: "ubuntu-latest" strategy: matrix: - python-version: ["3.11"] + python-version: ["3.14"] steps: - uses: "actions/checkout@v3" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8e13e01..a96e85a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,7 +14,7 @@ jobs: - name: "Set up Python" uses: "actions/setup-python@v4" with: - python-version: "3.9" + python-version: "3.12" - name: "Install build tool" run: "pip install --user build" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 86e82de..a4291c3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,9 +11,9 @@ jobs: strategy: matrix: python-version: - - "3.11" - - "3.10" - - "3.9" + - "3.14" + - "3.13" + - "3.12" pyqt-dependency: - "PyQt6" - "PySide6" diff --git a/README.rst b/README.rst index 90e5d3e..963d70e 100644 --- a/README.rst +++ b/README.rst @@ -14,7 +14,7 @@ Contact: Nathaniel J. Smith and Stéfan van der Walt Dependencies: - * Python 3.9+ + * Python 3.12+ * `colorspacious `_ 1.1+ * Matplotlib 3.5+ * NumPy 1.22+ diff --git a/environment.yml b/environment.yml index bf96902..772d85a 100644 --- a/environment.yml +++ b/environment.yml @@ -4,7 +4,7 @@ channels: - "nodefaults" dependencies: # Runtime - - "python ~=3.11" + - "python ~=3.12" - "numpy ~=1.24" - "matplotlib ~=3.7" - "colorspacious ~=1.1" diff --git a/pyproject.toml b/pyproject.toml index 3ded452..759c95e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,7 +15,7 @@ classifiers = [ "Programming Language :: Python :: 3", ] -requires-python = "~=3.9" +requires-python = ">=3.12" dependencies = [ "numpy ~=1.22", "matplotlib ~=3.5", @@ -60,7 +60,7 @@ package-data = {viscm = ["examples/*"]} [tool.mypy] -python_version = "3.9" +python_version = "3.12" # These libraries don't have type stubs. Mypy will see them as `Any` and not # throw an [import] error. @@ -74,10 +74,10 @@ ignore_missing_imports = true [tool.black] -target-version = ["py39", "py310", "py311"] +target-version = ["py312", "py313", "py314"] [tool.ruff] -target-version = "py39" +target-version = "py312" select = [ "F", "E", From 46a5d3223d750a6da11a3f9da769a00b8af24a17 Mon Sep 17 00:00:00 2001 From: Matt Fisher Date: Tue, 2 Jun 2026 15:25:23 -0600 Subject: [PATCH 02/10] Upgrade Black to support Python 3.12 and later --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b7cc1e3..32740ec 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,6 +15,6 @@ repos: args: ["--fix", "--exit-non-zero-on-fix"] - repo: "https://github.com/psf/black" - rev: "23.3.0" + rev: "26.5.1" hooks: - id: "black" From 41e817a6e5b9a87bba3babfb4223d4f3cd50f813 Mon Sep 17 00:00:00 2001 From: Matt Fisher Date: Tue, 2 Jun 2026 15:26:39 -0600 Subject: [PATCH 03/10] Upgrade Ruff to support Pythons 3.12 and later --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 32740ec..503079b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,7 +7,7 @@ repos: - id: "end-of-file-fixer" - repo: "https://github.com/charliermarsh/ruff-pre-commit" - rev: "v0.0.269" + rev: "v0.15.14" hooks: - id: "ruff" # NOTE: "--exit-non-zero-on-fix" is important for CI to function From 686ff55eccedda7e9ef0d9178610cd6d96e0a355 Mon Sep 17 00:00:00 2001 From: Matt Fisher Date: Tue, 2 Jun 2026 15:28:29 -0600 Subject: [PATCH 04/10] Apply linter and formatter autofixes --- test/data/option_d.py | 1 + viscm/cli.py | 9 ++++----- viscm/gui.py | 16 ++++------------ 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/test/data/option_d.py b/test/data/option_d.py index f2868b9..fd53f44 100644 --- a/test/data/option_d.py +++ b/test/data/option_d.py @@ -11,6 +11,7 @@ You should have received a copy of the CC0 legalcode along with this work. If not, see . """ + from matplotlib.colors import LinearSegmentedColormap # Used to reconstruct the colormap in viscm diff --git a/viscm/cli.py b/viscm/cli.py index af1cd47..40b848e 100644 --- a/viscm/cli.py +++ b/viscm/cli.py @@ -1,6 +1,5 @@ import sys from pathlib import Path -from typing import Union import matplotlib.pyplot as plt @@ -117,13 +116,13 @@ def cli(): def _make_window( *, action: str, - cmap: Union[str, None], + cmap: str | None, cmap_type: str, cmap_spline_method: str, cmap_uniform_space: str, - save: Union[Path, None], + save: Path | None, quit_immediately: bool, -) -> Union[gui.ViewerWindow, gui.EditorWindow]: +) -> gui.ViewerWindow | gui.EditorWindow: # Hold a reference so it doesn't get GC'ed fig = plt.figure() figure_canvas = gui.FigureCanvas(fig) @@ -132,7 +131,7 @@ def _make_window( if cmap: cm.load(cmap) - v: Union[gui.viscm, gui.viscm_editor] + v: gui.viscm | gui.viscm_editor # Easter egg! I keep typing 'show' instead of 'view' so accept both if action in ("view", "show"): if cm is None: diff --git a/viscm/gui.py b/viscm/gui.py index 01a33d7..88db140 100644 --- a/viscm/gui.py +++ b/viscm/gui.py @@ -284,9 +284,7 @@ def delta_ymax(values): title(ax, "Perceptual derivative") label( ax, - "Length: {:0.1f}\nRMS deviation from flat: {:0.1f} ({:0.1f}%)".format( - arclength, rmse, 100 * rmse / arclength - ), + f"Length: {arclength:0.1f}\nRMS deviation from flat: {rmse:0.1f} ({100 * rmse / arclength:0.1f}%)", ) ax.set_ylim(-delta_ymax(-local_derivs), delta_ymax(local_derivs)) ax.get_xaxis().set_visible(False) @@ -308,11 +306,7 @@ def delta_ymax(values): lightness_rmse = np.std(lightness_derivs) label( ax, - "Length: {:0.1f}\nRMS deviation from flat: {:0.1f} ({:0.1f}%)".format( - lightness_arclength, - lightness_rmse, - 100 * lightness_rmse / lightness_arclength, - ), + f"Length: {lightness_arclength:0.1f}\nRMS deviation from flat: {lightness_rmse:0.1f} ({100 * lightness_rmse / lightness_arclength:0.1f}%)", ) ax.set_ylim(-delta_ymax(-lightness_derivs), delta_ymax(lightness_derivs)) @@ -707,16 +701,14 @@ def save_colormap(self, filepath): def export_py(self, filepath): import textwrap - template = textwrap.dedent( - """ + template = textwrap.dedent(""" from matplotlib.colors import ListedColormap cm_type = "{type}" cm_data = {array_list} test_cm = ListedColormap(cm_data, name="{name}") - """ - ) + """) rgb, _ = self.cmap_model.get_sRGB(num=256) array_list = np.array2string( rgb, max_line_width=78, prefix="cm_data = ", separator="," From 8b7c3fde6d494ba858c630d159a66e3eeccc20fb Mon Sep 17 00:00:00 2001 From: Matt Fisher Date: Tue, 2 Jun 2026 15:30:05 -0600 Subject: [PATCH 05/10] Use correct new Ruff table names --- pyproject.toml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 759c95e..da7c5e4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -78,6 +78,8 @@ target-version = ["py312", "py313", "py314"] [tool.ruff] target-version = "py312" + +[tool.ruff.lint] select = [ "F", "E", @@ -94,8 +96,8 @@ select = [ "RUF", ] -[tool.ruff.per-file-ignores] +[tool.ruff.lint.per-file-ignores] "viscm/gui.py" = ["N8"] -[tool.ruff.mccabe] +[tool.ruff.lint.mccabe] max-complexity = 11 From 7ce017931018a65be802008953d5ad6608a0049e Mon Sep 17 00:00:00 2001 From: Matt Fisher Date: Tue, 2 Jun 2026 15:30:58 -0600 Subject: [PATCH 06/10] Use correct new ruff hook id --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 503079b..a3de1ea 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,7 +9,7 @@ repos: - repo: "https://github.com/charliermarsh/ruff-pre-commit" rev: "v0.15.14" hooks: - - id: "ruff" + - id: "ruff-check" # NOTE: "--exit-non-zero-on-fix" is important for CI to function # correctly! args: ["--fix", "--exit-non-zero-on-fix"] From d6a375ff785375bd28260efe003b2bec4d67936a Mon Sep 17 00:00:00 2001 From: Matt Fisher Date: Tue, 2 Jun 2026 15:33:01 -0600 Subject: [PATCH 07/10] Remove redundant info about python version for lint/format tools MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Clément Robert <14075922+neutrinoceros@users.noreply.github.com> --- pyproject.toml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index da7c5e4..c6f9b1e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -73,12 +73,6 @@ module = [ ignore_missing_imports = true -[tool.black] -target-version = ["py312", "py313", "py314"] - -[tool.ruff] -target-version = "py312" - [tool.ruff.lint] select = [ "F", From 741729e680c5240a13a18467e50c7dfc0829ce6c Mon Sep 17 00:00:00 2001 From: Matt Fisher Date: Tue, 2 Jun 2026 15:36:33 -0600 Subject: [PATCH 08/10] Ignore new lint errors --- pyproject.toml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index c6f9b1e..94946da 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -89,6 +89,13 @@ select = [ "T10", "RUF", ] +ignore = [ + "B905", + "UP031", + "RUF005", + "RUF046", + "RUF059", +] [tool.ruff.lint.per-file-ignores] "viscm/gui.py" = ["N8"] From 857441e6bd279192253548b5a81ea91b0327e849 Mon Sep 17 00:00:00 2001 From: Matt Fisher Date: Tue, 2 Jun 2026 15:39:20 -0600 Subject: [PATCH 09/10] Fix line-too-long lint complaint --- viscm/gui.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/viscm/gui.py b/viscm/gui.py index 88db140..eb74c43 100644 --- a/viscm/gui.py +++ b/viscm/gui.py @@ -284,7 +284,9 @@ def delta_ymax(values): title(ax, "Perceptual derivative") label( ax, - f"Length: {arclength:0.1f}\nRMS deviation from flat: {rmse:0.1f} ({100 * rmse / arclength:0.1f}%)", + f"Length: {arclength:0.1f}" + f"\nRMS deviation from flat: {rmse:0.1f}" + f" ({100 * rmse / arclength:0.1f}%)", ) ax.set_ylim(-delta_ymax(-local_derivs), delta_ymax(local_derivs)) ax.get_xaxis().set_visible(False) @@ -306,7 +308,9 @@ def delta_ymax(values): lightness_rmse = np.std(lightness_derivs) label( ax, - f"Length: {lightness_arclength:0.1f}\nRMS deviation from flat: {lightness_rmse:0.1f} ({100 * lightness_rmse / lightness_arclength:0.1f}%)", + f"Length: {lightness_arclength:0.1f}" + f"\nRMS deviation from flat: {lightness_rmse:0.1f}" + f" ({100 * lightness_rmse / lightness_arclength:0.1f}%)", ) ax.set_ylim(-delta_ymax(-lightness_derivs), delta_ymax(lightness_derivs)) From 643df9bea380ad906ee0cd14cfdda39ab29030ea Mon Sep 17 00:00:00 2001 From: Matt Fisher Date: Tue, 2 Jun 2026 15:41:51 -0600 Subject: [PATCH 10/10] Switch from dependency compatibility spec to lower-bound --- pyproject.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 94946da..6f7a2a1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,10 +17,10 @@ classifiers = [ requires-python = ">=3.12" dependencies = [ - "numpy ~=1.22", - "matplotlib ~=3.5", - "colorspacious ~=1.1", - "scipy ~=1.8", + "numpy >=1.22", + "matplotlib >=3.5", + "colorspacious >=1.1", + "scipy >=1.8", ] [project.optional-dependencies]