diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 65d8cc4..f31e3a8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,7 +38,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] steps: - uses: actions/checkout@v6 diff --git a/noxfile.py b/noxfile.py index bf0903b..6eb862a 100644 --- a/noxfile.py +++ b/noxfile.py @@ -7,7 +7,7 @@ import nox DIR = Path(__file__).parent.resolve() -ALL_PYTHON = ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] +ALL_PYTHON = ["3.10", "3.11", "3.12", "3.13", "3.14"] nox.needs_version = ">=2024.3.2" nox.options.sessions = ["lint", "tests"] diff --git a/pyproject.toml b/pyproject.toml index b2b6ae1..8cce909 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,7 +15,7 @@ authors = [ description = "Histogramming tools on CUDA." readme = "README.md" license.file = "LICENSE" -requires-python = ">=3.8" +requires-python = ">=3.10" classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Science/Research", @@ -25,12 +25,11 @@ classifiers = [ "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Topic :: Scientific/Engineering", "Typing :: Typed", ] @@ -99,7 +98,7 @@ report.exclude_also = [ [tool.mypy] files = ["src", "tests"] -python_version = "3.8" +python_version = "3.10" warn_unused_configs = true strict = true enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"] @@ -166,7 +165,7 @@ isort.required-imports = ["from __future__ import annotations"] [tool.pylint] -py-version = "3.8" +py-version = "3.10" ignore-paths = [".*/_version.py"] reports.output-format = "colorized" similarities.ignore-imports = "yes" diff --git a/src/cuda_histogram/axis/__init__.py b/src/cuda_histogram/axis/__init__.py index 34a4057..2ddaa6e 100644 --- a/src/cuda_histogram/axis/__init__.py +++ b/src/cuda_histogram/axis/__init__.py @@ -3,7 +3,7 @@ import functools import numbers import warnings -from typing import Iterable +from collections.abc import Iterable import awkward import cupy @@ -414,7 +414,7 @@ class Bin(DenseAxis): def __init__(self, n_or_arr, lo=None, hi=None, *, name="", label=""): self._lazy_intervals = None - if isinstance(n_or_arr, (list, np.ndarray, cupy.ndarray)): + if isinstance(n_or_arr, list | np.ndarray | cupy.ndarray): self._uniform = False self._bins = cupy.array(n_or_arr, dtype="d") if not all(np.sort(self._bins) == self._bins): @@ -454,7 +454,10 @@ def _intervals(self): self._lazy_intervals = [ Interval(low, high, bin) for low, high, bin in zip( - self._interval_bins[:-1], self._interval_bins[1:], self._bin_names + self._interval_bins[:-1], + self._interval_bins[1:], + self._bin_names, + strict=False, ) ] return self._lazy_intervals @@ -485,7 +488,7 @@ def index(self, identifier): The integer range includes flow bins: ``0 = underflow, n+1 = overflow, n+2 = nanflow`` """ isarray = isinstance( - identifier, (awkward.Array, cupy.ndarray, np.ndarray, list) + identifier, awkward.Array | cupy.ndarray | np.ndarray | list ) if isarray or isinstance(identifier, numbers.Number): identifier = awkward.to_cupy(identifier) # cupy.asarray(identifier) @@ -506,7 +509,7 @@ def index(self, identifier): self._bins + 1, ) - if isinstance(idx, (cupy.ndarray, np.ndarray)): + if isinstance(idx, cupy.ndarray | np.ndarray): _replace_nans( self.size - 1, idx if idx.dtype.kind == "f" else idx.astype(cupy.float32), @@ -630,7 +633,7 @@ def size(self): """Number of bins""" return ( self._bins - if isinstance(self._bins, (int, np.integer, cupy.integer)) + if isinstance(self._bins, int | np.integer | cupy.integer) else len(self._bins) ) diff --git a/src/cuda_histogram/hist.py b/src/cuda_histogram/hist.py index 6de8561..61aa3f0 100644 --- a/src/cuda_histogram/hist.py +++ b/src/cuda_histogram/hist.py @@ -140,11 +140,11 @@ def _init_sumw2(self): # TODO: should allow better indexing (UHI) def __getitem__(self, keys): if isinstance(keys, slice) and not all( - isinstance(s, (int, float)) or s is None + isinstance(s, int | float) or s is None for s in [keys.start, keys.stop, keys.step] ): raise ValueError("use to_boost/to_hist to access other UHI functionalities") - if not isinstance(keys, slice) and not isinstance(keys, (int, float, tuple)): + if not isinstance(keys, slice) and not isinstance(keys, int | float | tuple): raise ValueError("use to_boost/to_hist to access other UHI functionalities") if not isinstance(keys, tuple): keys = (keys,) @@ -161,7 +161,7 @@ def __getitem__(self, keys): sparse_idx = [] dense_idx = [] new_dims = [] - for s, ax in zip(keys, self._axes): + for s, ax in zip(keys, self._axes, strict=False): if isinstance(ax, SparseAxis): sparse_idx.append(ax._ireduce(s)) new_dims.append(ax) @@ -180,7 +180,9 @@ def dense_op(array): if self._sumw2 is not None: out._init_sumw2() for sparse_key in self._sumw: - if not all(k in idx for k, idx in zip(sparse_key, sparse_idx)): + if not all( + k in idx for k, idx in zip(sparse_key, sparse_idx, strict=False) + ): continue if sparse_key in out._sumw: out._sumw[sparse_key] += dense_op(self._sumw[sparse_key]) @@ -203,7 +205,7 @@ def fill(self, *args, weight=None): weight : cupy.ndarray Provide weights. """ - if not all(isinstance(a, (cupy.ndarray, str)) for a in args): + if not all(isinstance(a, cupy.ndarray | str) for a in args): raise TypeError("pass CuPy arrays") if weight is not None and not isinstance(weight, cupy.ndarray): raise TypeError("pass CuPy arrays") @@ -216,7 +218,7 @@ def fill(self, *args, weight=None): sparse_key = tuple( d.index(value) - for d, value in zip(self._axes, args) + for d, value in zip(self._axes, args, strict=False) if isinstance(d, SparseAxis) ) @@ -232,7 +234,7 @@ def fill(self, *args, weight=None): if self.dense_dim() > 0: dense_indices = tuple( cupy.asarray(d.index(value)) - for d, value in zip(self._axes, args) + for d, value in zip(self._axes, args, strict=False) if isinstance(d, DenseAxis) ) xy = cupy.atleast_1d(