diff --git a/.codespellrc b/.codespellrc index 15340eef6..3d04e4f4a 100644 --- a/.codespellrc +++ b/.codespellrc @@ -1,5 +1,5 @@ [codespell] -skip = .git,*.pdf,*.svg,*.html,dataset_description.json,*.bib +skip = .git,.maint/*,*.pdf,*.svg,*.html,dataset_description.json,*.bib # te - TE # Weill - name # reson - Reson. abbreviation in citation diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e7eea3e32..b432d1a5c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -34,22 +34,22 @@ jobs: strategy: matrix: os: ['ubuntu-latest'] - python-version: ['3.10', '3.11', '3.12', '3.13'] + python-version: ['3.12', '3.13', '3.14'] dependencies: ['latest', 'pre'] include: - os: ubuntu-latest - python-version: '3.10' + python-version: '3.12' dependencies: 'min' env: DEPENDS: ${{ matrix.dependencies }} steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: submodules: recursive fetch-depth: 0 - - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: ~/.cache/templateflow key: templateflow-v1 @@ -58,9 +58,9 @@ jobs: sudo apt update sudo apt install -y --no-install-recommends graphviz - name: Install the latest version of uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 + uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: ${{ matrix.python-version }} - name: Display Python version @@ -75,30 +75,7 @@ jobs: - name: Minimize uv cache run: uv cache prune --ci if: ${{ always() }} - - uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0 + - uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 with: token: ${{ secrets.CODECOV_TOKEN }} if: ${{ always() }} - - checks: - runs-on: "ubuntu-latest" - continue-on-error: true - strategy: - matrix: - check: ["style", "spellcheck"] - - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - - name: Install the latest version of uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 - - name: Install tox - run: uv tool install tox --with=tox-uv - - name: Show tox config - run: tox c -e ${{ matrix.check }} - - name: Run check - run: tox -e ${{ matrix.check }} - - name: Minimize uv cache - run: uv cache prune --ci - if: ${{ always() }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index de28b50f2..66177de54 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,5 +24,9 @@ repos: - id: ruff-check args: [ --fix, --show-fixes ] - id: ruff-format + - repo: https://github.com/codespell-project/codespell + rev: 57b21406f092110c18776e39b0bda50d37c945c8 # frozen: v2.4.3 + hooks: + - id: codespell ci: autoupdate_schedule: monthly diff --git a/.readthedocs.yml b/.readthedocs.yml index ea1d66257..a74c2881d 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -3,7 +3,7 @@ version: 2 build: os: ubuntu-22.04 tools: - python: "3.11" + python: "3.12" apt_packages: - graphviz jobs: diff --git a/fmriprep/cli/tests/test_version.py b/fmriprep/cli/tests/test_version.py index 66ee16056..26a2cfe48 100644 --- a/fmriprep/cli/tests/test_version.py +++ b/fmriprep/cli/tests/test_version.py @@ -22,7 +22,7 @@ # """Test version checks.""" -from datetime import datetime, timezone +from datetime import UTC, datetime from os import getenv, geteuid from pathlib import Path @@ -72,7 +72,7 @@ def mock_get(*args, **kwargs): assert v == Version('1.1.0') assert cachefile.read_text().split('|') == [ str(v), - datetime.now(tz=timezone.utc).strftime(DATE_FMT), + datetime.now(tz=UTC).strftime(DATE_FMT), ] # Second check - test the cache file is read @@ -140,7 +140,7 @@ def mock_get(*args, **kwargs): [ '3laj#r???d|3akajdf#', '2.0.0|3akajdf#', - '|'.join(('2.0.0', datetime.now(tz=timezone.utc).strftime(DATE_FMT), '')), + '|'.join(('2.0.0', datetime.now(tz=UTC).strftime(DATE_FMT), '')), '', ], ) diff --git a/fmriprep/cli/version.py b/fmriprep/cli/version.py index 1717cb808..7e2891649 100644 --- a/fmriprep/cli/version.py +++ b/fmriprep/cli/version.py @@ -23,7 +23,7 @@ """Version CLI helpers.""" from contextlib import suppress -from datetime import datetime, timezone +from datetime import UTC, datetime from pathlib import Path import requests @@ -41,7 +41,7 @@ def check_latest(): latest = None date = None outdated = None - now = datetime.now(tz=timezone.utc) + now = datetime.now(tz=UTC) cachefile = Path.home() / '.cache' / 'fmriprep' / 'latest' try: cachefile.parent.mkdir(parents=True, exist_ok=True) @@ -56,7 +56,7 @@ def check_latest(): else: try: latest = Version(latest) - date = datetime.strptime(date, DATE_FMT).astimezone(timezone.utc) + date = datetime.strptime(date, DATE_FMT).astimezone(UTC) except (InvalidVersion, ValueError): latest = None else: diff --git a/fmriprep/utils/asynctools.py b/fmriprep/utils/asynctools.py index 8d92a69ad..e6591daa3 100644 --- a/fmriprep/utils/asynctools.py +++ b/fmriprep/utils/asynctools.py @@ -1,11 +1,8 @@ import asyncio from collections.abc import Callable -from typing import TypeVar -R = TypeVar('R') - -async def worker(job: Callable[[], R], semaphore: asyncio.Semaphore) -> R: +async def worker[R](job: Callable[[], R], semaphore: asyncio.Semaphore) -> R: async with semaphore: loop = asyncio.get_running_loop() return await loop.run_in_executor(None, job) diff --git a/pyproject.toml b/pyproject.toml index b6a9da3a8..12056f101 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,37 +15,36 @@ classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Science/Research", "Topic :: Scientific/Engineering :: Image Recognition", - "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", ] license = "Apache-2.0" license-files = ["LICENSE"] -requires-python = ">=3.10" +requires-python = ">=3.12" dependencies = [ - "acres >= 0.2.0", + "acres >= 0.5.0", "looseversion >= 1.3", - "nibabel >= 5.1.1", + "nibabel >= 5.3.0", "nipype >= 1.9.0", - "nireports >= 24.1.0", - "nitime >= 0.9", + "nireports >= 25.0.1", + "nitime >= 0.12", "nitransforms >= 25.0.1", "niworkflows >= 1.14.4", - "numpy >= 2.0", - "packaging >= 24", - "pandas >= 2.2", - "psutil >= 5.4", - "pybids >= 0.16", - "requests >= 2.27", + "numpy >= 2.1", + "packaging >= 24.2", + "pandas >= 2.2.3", + "psutil >= 6.1.0", + "pybids >= 0.21", + "requests >= 2.32.4", "sdcflows >= 2.15.0", "smriprep >= 0.19.2", "tedana >= 25.1.0", "templateflow >= 24.2.2", "transforms3d >= 0.4.2", "toml >= 0.10", - "codecarbon >= 2", - "APScheduler >= 3.10", + "codecarbon >= 2.7.0", + "APScheduler >= 3.11.0", ] dynamic = ["version"] @@ -77,14 +76,14 @@ container = [ ] telemetry = [ "migas >= 0.4.0", - "sentry-sdk >= 1.3", + "sentry-sdk >= 2.13.0", ] test = [ - "coverage[toml] >= 5.2.1", - "pytest >= 8.1", - "pytest-cov >= 2.11", - "pytest-env", - "pytest-xdist >= 2.5", + "coverage[toml] >= 7.6.2", + "pytest >= 8.3.3", + "pytest-cov >= 6.0.0", + "pytest-env >= 1.1.4", + "pytest-xdist >= 3.7.0", ] maint = [ "fuzzywuzzy", diff --git a/tox.ini b/tox.ini index dace3d2b9..717870ee1 100644 --- a/tox.ini +++ b/tox.ini @@ -2,17 +2,16 @@ requires = tox>=4 envlist = - py3{10,11,12,13}-{latest,pre} - py310-min + py3{12,13,14}-{latest,pre} + py312-min skip_missing_interpreters = true # Configuration that allows us to split tests across GitHub runners effectively [gh-actions] python = - 3.10: py310 - 3.11: py311 3.12: py312 3.13: py313 + 3.14: py314 [gh-actions:env] DEPENDS = @@ -49,39 +48,10 @@ uv_resolution = commands_pre = # Use py* to disable for other environments - py3{10,11,12,13}: python scripts/fetch_templates.py + py3{12,13,14}: python scripts/fetch_templates.py commands = pytest --cov-report term-missing --durations=20 --durations-min=1.0 {posargs:-n auto} -[testenv:style] -description = Check our style guide -labels = check -deps = - ruff -skip_install = true -commands = - ruff check --diff - ruff format --diff - -[testenv:style-fix] -description = Auto-apply style guide to the extent possible -labels = pre-release -deps = - ruff -skip_install = true -commands = - ruff check --fix - ruff format - -[testenv:spellcheck] -description = Check spelling -labels = check -deps = - codespell[toml] -skip_install = true -commands = - codespell . {posargs} - [testenv:build{,-strict}] labels = check