From 252a8b177e7a1a01ac4c2979cc11e92514ddb159 Mon Sep 17 00:00:00 2001 From: Matt Graham Date: Fri, 23 May 2025 21:50:11 +0100 Subject: [PATCH 1/4] Update python_requires and test matrix --- .github/workflows/tests.yml | 7 ++----- pyproject.toml | 10 ++++------ 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index da86f094..12a5b699 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -27,11 +27,8 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] - os: [ubuntu-latest] - include: - - os: macos-latest - python-version: "3.8" + python-version: ["3.11", "3.12", "3.13"] + os: [ubuntu-latest, macos-latest] fail-fast: false env: CMAKE_POLICY_VERSION_MINIMUM: 3.5 diff --git a/pyproject.toml b/pyproject.toml index 6e05c936..599cd789 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,8 +2,8 @@ requires = [ "setuptools", "setuptools-scm", - "scikit-build-core >=0.4.3", - "nanobind >=1.3.2" + "scikit-build-core>=0.4.3", + "nanobind>=1.3.2" ] build-backend = "scikit_build_core.build" @@ -16,11 +16,9 @@ authors = [ classifiers = [ "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", "Operating System :: OS Independent", "Intended Audience :: Developers", "Intended Audience :: Science/Research", @@ -38,7 +36,7 @@ keywords = [ ] name = "s2fft" readme = "README.md" -requires-python = ">=3.8" +requires-python = ">=3.11" license.file = "LICENCE.txt" urls.homepage = "https://github.com/astro-informatics/s2fft" From cfb0484a65f483a432fd99b8c12d437621ad5672 Mon Sep 17 00:00:00 2001 From: Matt Graham Date: Fri, 23 May 2025 22:05:10 +0100 Subject: [PATCH 2/4] Ruff autofixes for type hints with 3.11+ features --- benchmarks/benchmarking.py | 5 ++++- benchmarks/plotting.py | 4 ++-- s2fft/precompute_transforms/construct.py | 5 ++--- s2fft/precompute_transforms/custom_ops.py | 13 ++++++------- s2fft/precompute_transforms/spherical.py | 9 ++++----- s2fft/recursions/price_mcewen.py | 9 ++++----- s2fft/sampling/s2_samples.py | 8 +++----- s2fft/sampling/so3_samples.py | 8 +++----- s2fft/transforms/otf_recursions.py | 9 ++++----- s2fft/transforms/spherical.py | 17 ++++++++--------- s2fft/transforms/wigner.py | 13 ++++++------- s2fft/utils/iterative_refinement.py | 3 ++- s2fft/utils/jax_primitive.py | 10 +++++----- s2fft/utils/rotation.py | 3 +-- s2fft/utils/torch_wrapper.py | 9 ++++++--- 15 files changed, 60 insertions(+), 65 deletions(-) diff --git a/benchmarks/benchmarking.py b/benchmarks/benchmarking.py index bbf4a312..057b3480 100644 --- a/benchmarks/benchmarking.py +++ b/benchmarks/benchmarking.py @@ -252,7 +252,10 @@ def _format_results_entry(results_entry: dict) -> str: def _dict_product(dicts: dict[str, Iterable[Any]]) -> Iterable[dict[str, Any]]: """Generator corresponding to Cartesian product of dictionaries.""" - return (dict(zip(dicts.keys(), values)) for values in product(*dicts.values())) + return ( + dict(zip(dicts.keys(), values, strict=False)) + for values in product(*dicts.values()) + ) def _parse_value(value: str) -> Any: diff --git a/benchmarks/plotting.py b/benchmarks/plotting.py index d19cd0e3..f809e8c8 100644 --- a/benchmarks/plotting.py +++ b/benchmarks/plotting.py @@ -141,10 +141,10 @@ def plot_results_against_bandlimit( squeeze=False, ) axes = axes.T if functions_along_columns else axes - for axes_row, function in zip(axes, functions): + for axes_row, function in zip(axes, functions, strict=False): results = benchmark_results["results"][function] l_values = np.array([r["parameters"]["L"] for r in results]) - for ax, measurement in zip(axes_row, measurements): + for ax, measurement in zip(axes_row, measurements, strict=False): plot_function, label = _measurement_plot_functions_and_labels[measurement] try: plot_function(ax, "L", l_values, results) diff --git a/s2fft/precompute_transforms/construct.py b/s2fft/precompute_transforms/construct.py index db1ed57f..90c0179e 100644 --- a/s2fft/precompute_transforms/construct.py +++ b/s2fft/precompute_transforms/construct.py @@ -1,4 +1,3 @@ -from typing import Tuple from warnings import warn import jax @@ -612,7 +611,7 @@ def wigner_kernel_jax( wigner_kernel_torch = torch_wrapper.wrap_as_torch_function(wigner_kernel_jax) -def fourier_wigner_kernel(L: int) -> Tuple[np.ndarray, np.ndarray]: +def fourier_wigner_kernel(L: int) -> tuple[np.ndarray, np.ndarray]: """ Computes Fourier coefficients of the reduced Wigner d-functions and quadrature weights upsampled for the forward Fourier-Wigner transform. @@ -640,7 +639,7 @@ def fourier_wigner_kernel(L: int) -> Tuple[np.ndarray, np.ndarray]: return deltas, w -def fourier_wigner_kernel_jax(L: int) -> Tuple[jnp.ndarray, jnp.ndarray]: +def fourier_wigner_kernel_jax(L: int) -> tuple[jnp.ndarray, jnp.ndarray]: """ Computes Fourier coefficients of the reduced Wigner d-functions and quadrature weights upsampled for the forward Fourier-Wigner transform (JAX implementation). diff --git a/s2fft/precompute_transforms/custom_ops.py b/s2fft/precompute_transforms/custom_ops.py index a220824f..b6a84da3 100644 --- a/s2fft/precompute_transforms/custom_ops.py +++ b/s2fft/precompute_transforms/custom_ops.py @@ -1,5 +1,4 @@ from functools import partial -from typing import Tuple import jax.numpy as jnp import numpy as np @@ -9,7 +8,7 @@ def wigner_subset_to_s2( flmn: np.ndarray, spins: np.ndarray, - DW: Tuple[np.ndarray, np.ndarray], + DW: tuple[np.ndarray, np.ndarray], L: int, sampling: str = "mw", ) -> np.ndarray: @@ -91,7 +90,7 @@ def wigner_subset_to_s2( def wigner_subset_to_s2_jax( flmn: jnp.ndarray, spins: jnp.ndarray, - DW: Tuple[jnp.ndarray, jnp.ndarray], + DW: tuple[jnp.ndarray, jnp.ndarray], L: int, sampling: str = "mw", ) -> jnp.ndarray: @@ -173,7 +172,7 @@ def wigner_subset_to_s2_jax( def so3_to_wigner_subset( f: np.ndarray, spins: np.ndarray, - DW: Tuple[np.ndarray, np.ndarray], + DW: tuple[np.ndarray, np.ndarray], L: int, N: int, sampling: str = "mw", @@ -214,7 +213,7 @@ def so3_to_wigner_subset( def so3_to_wigner_subset_jax( f: jnp.ndarray, spins: jnp.ndarray, - DW: Tuple[jnp.ndarray, jnp.ndarray], + DW: tuple[jnp.ndarray, jnp.ndarray], L: int, N: int, sampling: str = "mw", @@ -257,7 +256,7 @@ def so3_to_wigner_subset_jax( def s2_to_wigner_subset( fs: np.ndarray, spins: np.ndarray, - DW: Tuple[np.ndarray, np.ndarray], + DW: tuple[np.ndarray, np.ndarray], L: int, sampling: str = "mw", ) -> np.ndarray: @@ -343,7 +342,7 @@ def s2_to_wigner_subset( def s2_to_wigner_subset_jax( fs: jnp.ndarray, spins: jnp.ndarray, - DW: Tuple[jnp.ndarray, jnp.ndarray], + DW: tuple[jnp.ndarray, jnp.ndarray], L: int, sampling: str = "mw", ) -> jnp.ndarray: diff --git a/s2fft/precompute_transforms/spherical.py b/s2fft/precompute_transforms/spherical.py index 878f7173..c84c05e0 100644 --- a/s2fft/precompute_transforms/spherical.py +++ b/s2fft/precompute_transforms/spherical.py @@ -1,5 +1,4 @@ from functools import partial -from typing import Optional from warnings import warn import jax.numpy as jnp @@ -21,11 +20,11 @@ def inverse( flm: np.ndarray, L: int, spin: int = 0, - kernel: Optional[np.ndarray] = None, + kernel: np.ndarray | None = None, sampling: str = "mw", reality: bool = False, method: str = "jax", - nside: Optional[int] = None, + nside: int | None = None, ) -> np.ndarray: r""" Compute the inverse spherical harmonic transform via precompute. @@ -228,11 +227,11 @@ def forward( f: np.ndarray, L: int, spin: int = 0, - kernel: Optional[np.ndarray] = None, + kernel: np.ndarray | None = None, sampling: str = "mw", reality: bool = False, method: str = "jax", - nside: Optional[int] = None, + nside: int | None = None, iter: int = 0, ) -> np.ndarray: r""" diff --git a/s2fft/recursions/price_mcewen.py b/s2fft/recursions/price_mcewen.py index f9aa8f95..1c98253d 100644 --- a/s2fft/recursions/price_mcewen.py +++ b/s2fft/recursions/price_mcewen.py @@ -1,6 +1,5 @@ import warnings from functools import partial -from typing import List import jax.lax as lax import jax.numpy as jnp @@ -19,7 +18,7 @@ def generate_precomputes( nside: int = None, forward: bool = False, L_lower: int = 0, -) -> List[np.ndarray]: +) -> list[np.ndarray]: r""" Compute recursion coefficients with :math:`\mathcal{O}(L^3)` memory overhead. @@ -125,7 +124,7 @@ def generate_precomputes_jax( forward: bool = False, L_lower: int = 0, betas: jnp.ndarray = None, -) -> List[jnp.ndarray]: +) -> list[jnp.ndarray]: r""" Compute recursion coefficients with :math:`\mathcal{O}(L^2)` memory overhead. In practice one could compute these on-the-fly but the memory overhead is @@ -264,7 +263,7 @@ def generate_precomputes_wigner( forward: bool = False, reality: bool = False, L_lower: int = 0, -) -> List[List[np.ndarray]]: +) -> list[list[np.ndarray]]: r""" Compute recursion coefficients with :math:`\mathcal{O}(L^2)` memory overhead. In practice one could compute these on-the-fly but the memory overhead is @@ -316,7 +315,7 @@ def generate_precomputes_wigner_jax( forward: bool = False, reality: bool = False, L_lower: int = 0, -) -> List[List[jnp.ndarray]]: +) -> list[list[jnp.ndarray]]: r""" Compute recursion coefficients with :math:`\mathcal{O}(L^2)` memory overhead. In practice one could compute these on-the-fly but the memory overhead is diff --git a/s2fft/sampling/s2_samples.py b/s2fft/sampling/s2_samples.py index 06d1996b..6e8c8dc3 100644 --- a/s2fft/sampling/s2_samples.py +++ b/s2fft/sampling/s2_samples.py @@ -1,5 +1,3 @@ -from typing import Tuple - import numpy as np @@ -125,7 +123,7 @@ def nphi_equiang(L: int, sampling: str = "mw") -> int: return 1 -def ftm_shape(L: int, sampling: str = "mw", nside: int = None) -> Tuple[int, int]: +def ftm_shape(L: int, sampling: str = "mw", nside: int = None) -> tuple[int, int]: r""" Shape of intermediate array, before/after latitudinal step. @@ -445,7 +443,7 @@ def ring_phase_shift_hp( return np.exp(sign * 1j * np.arange(m_start_ind, L) * phi_offset) -def f_shape(L: int = None, sampling: str = "mw", nside: int = None) -> Tuple[int]: +def f_shape(L: int = None, sampling: str = "mw", nside: int = None) -> tuple[int]: r""" Shape of spherical signal. @@ -480,7 +478,7 @@ def f_shape(L: int = None, sampling: str = "mw", nside: int = None) -> Tuple[int return ntheta(L, sampling), nphi_equiang(L, sampling) -def flm_shape(L: int) -> Tuple[int, int]: +def flm_shape(L: int) -> tuple[int, int]: r""" Standard shape of harmonic coefficients. diff --git a/s2fft/sampling/so3_samples.py b/s2fft/sampling/so3_samples.py index 1731606c..cd849125 100644 --- a/s2fft/sampling/so3_samples.py +++ b/s2fft/sampling/so3_samples.py @@ -1,5 +1,3 @@ -from typing import Tuple - import numpy as np from s2fft.sampling import s2_samples as samples @@ -7,7 +5,7 @@ def f_shape( L: int, N: int, sampling: str = "mw", nside: int = None -) -> Tuple[int, int, int]: +) -> tuple[int, int, int]: r""" Computes the pixel-space sampling shape for signal on the rotation group :math:`SO(3)`. @@ -49,7 +47,7 @@ def f_shape( raise ValueError(f"Sampling scheme sampling={sampling} not supported") -def flmn_shape(L: int, N: int) -> Tuple[int, int, int]: +def flmn_shape(L: int, N: int) -> tuple[int, int, int]: r""" Computes the shape of Wigner coefficients for signal on the rotation group :math:`SO(3)`. @@ -69,7 +67,7 @@ def flmn_shape(L: int, N: int) -> Tuple[int, int, int]: def fnab_shape( L: int, N: int, sampling: str = "mw", nside: int = None -) -> Tuple[int, int, int]: +) -> tuple[int, int, int]: r""" Computes the shape of Wigner coefficients for signal on the rotation group :math:`SO(3)`. diff --git a/s2fft/transforms/otf_recursions.py b/s2fft/transforms/otf_recursions.py index f3bd8c50..8eae9cfa 100644 --- a/s2fft/transforms/otf_recursions.py +++ b/s2fft/transforms/otf_recursions.py @@ -1,5 +1,4 @@ from functools import partial -from typing import List import jax.lax as lax import jax.numpy as jnp @@ -21,7 +20,7 @@ def inverse_latitudinal_step( nside: int, sampling: str = "mw", reality: bool = False, - precomps: List = None, + precomps: list = None, L_lower: int = 0, ) -> np.ndarray: r""" @@ -181,7 +180,7 @@ def inverse_latitudinal_step_jax( nside: int, sampling: str = "mw", reality: bool = False, - precomps: List = None, + precomps: list = None, spmd: bool = False, L_lower: int = 0, ) -> jnp.ndarray: @@ -438,7 +437,7 @@ def forward_latitudinal_step( nside: int, sampling: str = "mw", reality: bool = False, - precomps: List = None, + precomps: list = None, L_lower: int = 0, ) -> np.ndarray: r""" @@ -598,7 +597,7 @@ def forward_latitudinal_step_jax( nside: int, sampling: str = "mw", reality: bool = False, - precomps: List = None, + precomps: list = None, spmd: bool = False, L_lower: int = 0, ) -> jnp.ndarray: diff --git a/s2fft/transforms/spherical.py b/s2fft/transforms/spherical.py index 7d3ff051..92126ce6 100644 --- a/s2fft/transforms/spherical.py +++ b/s2fft/transforms/spherical.py @@ -1,5 +1,4 @@ from functools import partial -from typing import List, Optional import jax.numpy as jnp import numpy as np @@ -27,7 +26,7 @@ def inverse( sampling: str = "mw", method: str = "numpy", reality: bool = False, - precomps: List = None, + precomps: list = None, spmd: bool = False, L_lower: int = 0, _ssht_backend: int = 1, @@ -117,7 +116,7 @@ def inverse_numpy( nside: int = None, sampling: str = "mw", reality: bool = False, - precomps: List = None, + precomps: list = None, L_lower: int = 0, ) -> np.ndarray: r""" @@ -217,7 +216,7 @@ def inverse_jax( nside: int = None, sampling: str = "mw", reality: bool = False, - precomps: List = None, + precomps: list = None, spmd: bool = False, L_lower: int = 0, use_healpix_custom_primitive: bool = False, @@ -354,14 +353,14 @@ def forward( f: np.ndarray, L: int, spin: int = 0, - nside: Optional[int] = None, + nside: int | None = None, sampling: str = "mw", method: str = "numpy", reality: bool = False, - precomps: Optional[List] = None, + precomps: list | None = None, spmd: bool = False, L_lower: int = 0, - iter: Optional[int] = None, + iter: int | None = None, _ssht_backend: int = 1, ) -> np.ndarray: r""" @@ -472,7 +471,7 @@ def forward_numpy( nside: int = None, sampling: str = "mw", reality: bool = False, - precomps: List = None, + precomps: list = None, L_lower: int = 0, ) -> np.ndarray: r""" @@ -597,7 +596,7 @@ def forward_jax( nside: int = None, sampling: str = "mw", reality: bool = False, - precomps: List = None, + precomps: list = None, spmd: bool = False, L_lower: int = 0, use_healpix_custom_primitive: bool = False, diff --git a/s2fft/transforms/wigner.py b/s2fft/transforms/wigner.py index a9126b24..d388e00a 100644 --- a/s2fft/transforms/wigner.py +++ b/s2fft/transforms/wigner.py @@ -1,5 +1,4 @@ from functools import partial -from typing import List import jax.numpy as jnp import numpy as np @@ -19,7 +18,7 @@ def inverse( sampling: str = "mw", method: str = "numpy", reality: bool = False, - precomps: List = None, + precomps: list = None, L_lower: int = 0, _ssht_backend: int = 1, ) -> np.ndarray: @@ -115,7 +114,7 @@ def inverse_numpy( nside: int = None, sampling: str = "mw", reality: bool = False, - precomps: List = None, + precomps: list = None, L_lower: int = 0, ) -> np.ndarray: r""" @@ -205,7 +204,7 @@ def inverse_jax( nside: int = None, sampling: str = "mw", reality: bool = False, - precomps: List = None, + precomps: list = None, L_lower: int = 0, ) -> jnp.ndarray: r""" @@ -352,7 +351,7 @@ def forward( sampling: str = "mw", method: str = "numpy", reality: bool = False, - precomps: List = None, + precomps: list = None, L_lower: int = 0, _ssht_backend: int = 1, ) -> np.ndarray: @@ -447,7 +446,7 @@ def forward_numpy( nside: int = None, sampling: str = "mw", reality: bool = False, - precomps: List = None, + precomps: list = None, L_lower: int = 0, ) -> np.ndarray: r""" @@ -542,7 +541,7 @@ def forward_jax( nside: int = None, sampling: str = "mw", reality: bool = False, - precomps: List = None, + precomps: list = None, L_lower: int = 0, ) -> jnp.ndarray: r""" diff --git a/s2fft/utils/iterative_refinement.py b/s2fft/utils/iterative_refinement.py index c8d87f66..5ae19bc0 100644 --- a/s2fft/utils/iterative_refinement.py +++ b/s2fft/utils/iterative_refinement.py @@ -1,6 +1,7 @@ """Iterative scheme for improving accuracy of linear transforms.""" -from typing import Callable, TypeVar +from collections.abc import Callable +from typing import TypeVar T = TypeVar("T") diff --git a/s2fft/utils/jax_primitive.py b/s2fft/utils/jax_primitive.py index 6aac7c72..a2c02106 100644 --- a/s2fft/utils/jax_primitive.py +++ b/s2fft/utils/jax_primitive.py @@ -1,5 +1,5 @@ +from collections.abc import Callable from functools import partial -from typing import Callable, Dict, Optional, Union from jax import core from jax.interpreters import ad, batching, mlir, xla @@ -9,10 +9,10 @@ def register_primitive( name: str, multiple_results: bool, abstract_evaluation: Callable, - lowering_per_platform: Dict[Union[None, str], Callable], - batcher: Optional[Callable] = None, - jacobian_vector_product: Optional[Callable] = None, - transpose: Optional[Callable] = None, + lowering_per_platform: dict[None | str, Callable], + batcher: Callable | None = None, + jacobian_vector_product: Callable | None = None, + transpose: Callable | None = None, ): """ Register a new custom JAX primitive. diff --git a/s2fft/utils/rotation.py b/s2fft/utils/rotation.py index e29b4916..47f16f5d 100644 --- a/s2fft/utils/rotation.py +++ b/s2fft/utils/rotation.py @@ -1,5 +1,4 @@ from functools import partial -from typing import Tuple import jax.numpy as jnp from jax import jit @@ -11,7 +10,7 @@ def rotate_flms( flm: jnp.ndarray, L: int, - rotation: Tuple[float, float, float], + rotation: tuple[float, float, float], dl_array: jnp.ndarray = None, ) -> jnp.ndarray: """ diff --git a/s2fft/utils/torch_wrapper.py b/s2fft/utils/torch_wrapper.py index 1f12894f..6c680d28 100644 --- a/s2fft/utils/torch_wrapper.py +++ b/s2fft/utils/torch_wrapper.py @@ -32,10 +32,11 @@ from __future__ import annotations +from collections.abc import Callable from functools import wraps from inspect import getmembers, isroutine, signature from types import ModuleType -from typing import Any, Callable, Dict, List, Tuple, TypeVar, Union +from typing import Any, TypeVar import jax import jax.dlpack @@ -52,7 +53,7 @@ TORCH_AVAILABLE = False T = TypeVar("T") -PyTree = Union[Dict[Any, "PyTree"], List["PyTree"], Tuple["PyTree"], T] +PyTree = dict[Any, "PyTree"] | list["PyTree"] | tuple["PyTree"] | T def check_torch_available() -> None: @@ -201,7 +202,9 @@ def torch_function(*args, **kwargs): ) def jax_function_diff_args_only(*differentiable_args): - for key, value in zip(differentiable_argnames, differentiable_args): + for key, value in zip( + differentiable_argnames, differentiable_args, strict=False + ): bound_args.arguments[key] = value return jax_function(*bound_args.args, **bound_args.kwargs) From 4ffb75cc3dbfb8e021d48798e2f6da8360f3d856 Mon Sep 17 00:00:00 2001 From: Matt Graham Date: Mon, 9 Jun 2025 14:37:02 +0100 Subject: [PATCH 3/4] Limit test matrix and add tmate action to debug --- .github/workflows/tests.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 12a5b699..5f85e764 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -27,8 +27,8 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: ["3.11", "3.12", "3.13"] - os: [ubuntu-latest, macos-latest] + python-version: ["3.13"] + os: [macos-latest] fail-fast: false env: CMAKE_POLICY_VERSION_MINIMUM: 3.5 @@ -51,11 +51,11 @@ jobs: python -m pip install --upgrade pip pip install .[tests] + - name: Setup tmate session + uses: mxschmitt/action-tmate@v3 + with: + limit-access-to-actor: true + - name: Run tests run: | - pytest -v --cov-report=xml --cov=s2fft --cov-config=.coveragerc - - - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@v5 - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + pytest -vv tests/test_fourier_wigner.py::test_forward_fourier_wigner_transform_high_N[8966433580120847635-True-mwss-64] From 00a2184f04a237b5b708afc22e6820e4f399aad6 Mon Sep 17 00:00:00 2001 From: Matt Graham Date: Mon, 16 Jun 2025 15:52:45 +0100 Subject: [PATCH 4/4] Add workflow job step to setup Miniforge --- .github/workflows/tests.yml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index fbfecba5..bb9c0420 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -45,17 +45,22 @@ jobs: with: python-version: ${{ matrix.python-version }} cache: pip + + - name: Set up Miniforge + uses: conda-incubator/setup-miniconda@v3 + with: + miniforge-version: latest + + - name: Setup tmate session + uses: mxschmitt/action-tmate@v3 + with: + limit-access-to-actor: true - name: Install dependencies run: | python -m pip install --upgrade pip pip install .[tests] - - name: Setup tmate session - uses: mxschmitt/action-tmate@v3 - with: - limit-access-to-actor: true - - name: Run tests if: github.event_name != 'pull_request' run: |