diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8e9f98a25..de6ad2fde 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] platform: [ubuntu-latest, macos-latest, windows-latest] steps: @@ -77,32 +77,32 @@ jobs: deploy: name: Deploy needs: test - if: "success() && startsWith(github.ref, 'refs/tags/') && github.event_name != 'schedule'" + if: success() && startsWith(github.ref, 'refs/tags/') && github.event_name != 'schedule' runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Set up Python uses: actions/setup-python@v5 with: python-version: "3.x" - - name: install + - name: 👷 Build run: | - git tag - pip install -U pip - pip install -U build twine + python -m pip install build python -m build - twine check dist/* - ls -lh dist - - name: Build and publish - run: twine upload dist/* - env: - TWINE_USERNAME: __token__ - TWINE_PASSWORD: ${{ secrets.TWINE_API_KEY }} + - name: 🚢 Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 - uses: softprops/action-gh-release@v2 with: generate_release_notes: true + files: "./dist/*" diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 21ad0d990..68ec4c64b 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -12,7 +12,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: - python-version: '3.11' + python-version: '3.12' - run: | pip install -e .[docs] - run: mkdocs gh-deploy --strict --force diff --git a/docs/_hooks.py b/docs/_hooks.py index 1861252ab..f3e6056d3 100644 --- a/docs/_hooks.py +++ b/docs/_hooks.py @@ -1,9 +1,10 @@ import base64 import re import sys +from collections.abc import Sequence from functools import partial from pathlib import Path -from typing import TYPE_CHECKING, Any, Sequence, cast +from typing import TYPE_CHECKING, Any, cast import natsort import numpy as np diff --git a/pyproject.toml b/pyproject.toml index 224d526a5..1d41029f0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ build-backend = "hatchling.build" name = "cmap" description = "Scientific colormaps for python, without dependencies" readme = "README.md" -requires-python = ">=3.8" +requires-python = ">=3.9" license = "BSD-3-Clause" license-files = ["LICENSE/*"] authors = [{ email = "talley.lambert@gmail.com", name = "Talley Lambert" }] @@ -16,7 +16,6 @@ classifiers = [ "Development Status :: 4 - Beta", "License :: OSI Approved :: BSD License", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", @@ -50,8 +49,9 @@ test_thirdparty = [ "colorspacious", "colour", "matplotlib", - "napari>=0.4.19; python_version<'3.13'", - "numba; python_version<'3.13' and platform_machine != 'arm64'", + "napari>=0.5.0", + "numba", + "numba<0.61; python_version<'3.12'", "plotly", "pydantic-extra-types>=2,!=2.10.1", "pydantic", @@ -93,7 +93,7 @@ include = ["/src", "/tests", "CHANGELOG.md"] # https://github.com/charliermarsh/ruff [tool.ruff] line-length = 88 -target-version = "py38" +target-version = "py39" src = ["src"] [tool.ruff.lint] diff --git a/src/cmap/__init__.py b/src/cmap/__init__.py index 0964babde..359f24aff 100644 --- a/src/cmap/__init__.py +++ b/src/cmap/__init__.py @@ -1,7 +1,7 @@ """Scientific colormaps for python, without dependencies.""" from importlib.metadata import PackageNotFoundError, version -from typing import TYPE_CHECKING, Iterator, Mapping +from typing import TYPE_CHECKING try: __version__ = version("cmap") @@ -14,6 +14,8 @@ from ._util import to_mpl if TYPE_CHECKING: + from collections.abc import Iterator, Mapping + from ._catalog import CatalogItem class Catalog(Mapping[str, CatalogItem]): diff --git a/src/cmap/_catalog.py b/src/cmap/_catalog.py index 0f6c32067..d457a7684 100644 --- a/src/cmap/_catalog.py +++ b/src/cmap/_catalog.py @@ -10,18 +10,10 @@ import json import logging +from collections.abc import Container, Iterable, Iterator, Mapping from dataclasses import dataclass, field from pathlib import Path -from typing import ( - TYPE_CHECKING, - Any, - Container, - Iterable, - Iterator, - Literal, - Mapping, - cast, -) +from typing import TYPE_CHECKING, Any, Literal, cast import cmap.data diff --git a/src/cmap/_color.py b/src/cmap/_color.py index e4c4e9912..1c69e5e44 100644 --- a/src/cmap/_color.py +++ b/src/cmap/_color.py @@ -6,15 +6,13 @@ import contextlib import re import sys +from collections.abc import Iterable, Sequence from typing import ( TYPE_CHECKING, Any, Callable, - Iterable, - List, Literal, NamedTuple, - Sequence, SupportsFloat, Union, cast, @@ -53,7 +51,7 @@ RGBTuple, # 3-tuple of all ints or all floats RGBATuple, # 4-tuple of all floats, or 3 ints and 1 float np.ndarray, # 3- or 4-element rgb(a) vector - List[Union[float, int]], # 3- or 4-element rgb(a) vector + list[Union[float, int]], # 3- or 4-element rgb(a) vector "Color", # another color object ] """Data types that can be cast to a [cmap.Color][] instance. diff --git a/src/cmap/_colormap.py b/src/cmap/_colormap.py index 94854954c..ecfa920a3 100644 --- a/src/cmap/_colormap.py +++ b/src/cmap/_colormap.py @@ -4,21 +4,10 @@ import base64 import warnings +from collections.abc import Iterable, Sequence from functools import partial from numbers import Number -from typing import ( - TYPE_CHECKING, - Any, - Callable, - Dict, - Iterable, - NamedTuple, - Sequence, - Tuple, - Union, - cast, - overload, -) +from typing import TYPE_CHECKING, Any, Callable, NamedTuple, Union, cast, overload import numpy as np import numpy.typing as npt @@ -28,7 +17,8 @@ from ._color import Color, ColorLike if TYPE_CHECKING: - from typing import Iterator, Literal + from collections.abc import Iterator + from typing import Literal import bokeh.models import matplotlib.colors @@ -63,7 +53,7 @@ class ColormapDict(TypedDict): LutCallable: TypeAlias = Callable[["NDArray"], "NDArray"] """Function type for a callable that takes an array of values in the range [0, 1] and returns an (N, 4) array of RGBA values in the range [0, 1].""" # noqa -ColorStopLike: TypeAlias = Union[Tuple[float, ColorLike], "NDArray"] +ColorStopLike: TypeAlias = Union[tuple[float, ColorLike], "NDArray"] """A single color-stop: 2-tuple of a scalar "stop" value and a color-like object, or an array of color-like objects.""" # noqa # All of the things that we can pass to the constructor of Colormap @@ -72,7 +62,7 @@ class ColormapDict(TypedDict): Iterable[Union[ColorLike, ColorStopLike]], "NDArray", "MPLSegmentData", - Dict[float, ColorLike], + dict[float, ColorLike], "ColorStops", LutCallable, ] diff --git a/src/cmap/_util.py b/src/cmap/_util.py index 54b41589a..295efca6c 100644 --- a/src/cmap/_util.py +++ b/src/cmap/_util.py @@ -1,7 +1,7 @@ from __future__ import annotations import sys -from typing import TYPE_CHECKING, Sequence, TypedDict, cast +from typing import TYPE_CHECKING, TypedDict, cast import numpy as np @@ -9,6 +9,8 @@ gradient = np.vstack((gradient, gradient)) if TYPE_CHECKING: + from collections.abc import Sequence + import matplotlib.colors from matplotlib.figure import Figure as MplFigure from numpy.typing import ArrayLike, NDArray diff --git a/src/cmap/data/glasbey/_grids.py b/src/cmap/data/glasbey/_grids.py index 59e1965f5..18d6c4f53 100644 --- a/src/cmap/data/glasbey/_grids.py +++ b/src/cmap/data/glasbey/_grids.py @@ -2,7 +2,7 @@ # see __init__ and LICENSE_GLASBEY from __future__ import annotations -from typing import Sized +from collections.abc import Sized import numpy as np diff --git a/src/cmap/data/gnuplot/__init__.py b/src/cmap/data/gnuplot/__init__.py index 2dd9647f7..6283e48c1 100644 --- a/src/cmap/data/gnuplot/__init__.py +++ b/src/cmap/data/gnuplot/__init__.py @@ -52,8 +52,9 @@ # 36: 2*x - 1 """ +from collections.abc import Sequence from functools import partial -from typing import TYPE_CHECKING, Sequence +from typing import TYPE_CHECKING import numpy as np diff --git a/tests/test_data.py b/tests/test_data.py index 0eab60ab6..4357c48ac 100644 --- a/tests/test_data.py +++ b/tests/test_data.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING, Set, cast +from typing import TYPE_CHECKING, cast import numpy as np import numpy.testing as npt @@ -9,7 +9,7 @@ try: import matplotlib as mpl - MPL_CMAPS: Set[str] = {c for c in mpl.colormaps if not c.endswith("_r")} + MPL_CMAPS: set[str] = {c for c in mpl.colormaps if not c.endswith("_r")} except ImportError: MPL_CMAPS = {} @@ -32,7 +32,7 @@ def test_napari_name_parity() -> None: pytest.importorskip("napari") import napari.utils.colormaps.colormap_utils as ncm - napari_cmaps: Set[str] = set(ncm.AVAILABLE_COLORMAPS) + napari_cmaps: set[str] = set(ncm.AVAILABLE_COLORMAPS) napari_cmaps.update(ncm._VISPY_COLORMAPS_ORIGINAL) napari_cmaps.update(ncm._MATPLOTLIB_COLORMAP_NAMES) # TODO: later it would be good to make sure we can accept all strings