Skip to content

Commit 672675d

Browse files
authored
Adopt the Scientific Python deprecation schedule: (#3485)
1 parent 7baadb7 commit 672675d

File tree

14 files changed

+38
-86
lines changed

14 files changed

+38
-86
lines changed

.azure-pipelines.yml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ trigger:
33
- "*.*.x"
44

55
variables:
6-
python.version: '3.12'
6+
python.version: '3.13'
77
PYTEST_ADDOPTS: '-v --color=yes --internet-tests --nunit-xml=test-data/test-results.xml'
88
TEST_EXTRA: 'test-full'
99
DEPENDENCIES_VERSION: "latest" # |"pre-release" | "minimum-version"
@@ -15,16 +15,16 @@ jobs:
1515
vmImage: 'ubuntu-22.04'
1616
strategy:
1717
matrix:
18-
Python3.10:
19-
python.version: '3.10'
20-
Python3.12: {}
18+
Python3.11:
19+
python.version: '3.11'
20+
Python3.13: {}
2121
minimal_dependencies:
2222
TEST_EXTRA: 'test-min'
2323
anndata_dev:
2424
DEPENDENCIES_VERSION: "pre-release"
2525
TEST_TYPE: "coverage"
2626
minimum_versions:
27-
python.version: '3.10'
27+
python.version: '3.11'
2828
DEPENDENCIES_VERSION: "minimum-version"
2929
TEST_TYPE: "coverage"
3030

@@ -120,8 +120,8 @@ jobs:
120120

121121
- task: UsePythonVersion@0
122122
inputs:
123-
versionSpec: '3.12'
124-
displayName: 'Use Python 3.12'
123+
versionSpec: '3.13'
124+
displayName: 'Use Python 3.13'
125125

126126
- script: |
127127
python -m pip install --upgrade pip

.github/workflows/benchmark.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
strategy:
1717
fail-fast: false
1818
matrix:
19-
python: ["3.12"]
19+
python: ["3.13"]
2020
os: [ubuntu-latest]
2121

2222
env:

.readthedocs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ submodules:
44
build:
55
os: ubuntu-24.04
66
tools:
7-
python: '3.12'
7+
python: '3.13'
88
jobs:
99
post_checkout:
1010
# unshallow so version can be derived from tag

benchmarks/asv.conf.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454

5555
// The Pythons you'd like to test against. If not provided, defaults
5656
// to the current version of Python used to run `asv`.
57-
// "pythons": ["3.10", "3.12"],
57+
// "pythons": ["3.11", "3.13"],
5858

5959
// The list of conda channel names to be searched for benchmark
6060
// dependency packages in the specified order

ci/scripts/min-deps.py

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,21 @@
11
#!/usr/bin/env python3
22
# /// script
3-
# dependencies = [
4-
# "tomli; python_version < '3.11'",
5-
# "packaging",
6-
# ]
3+
# requires-python = ">=3.11"
4+
# dependencies = [ "packaging" ]
75
# ///
86
"""Parse a pyproject.toml file and output a list of minimum dependencies."""
97

108
from __future__ import annotations
119

1210
import argparse
1311
import sys
12+
import tomllib
1413
from collections import deque
1514
from contextlib import ExitStack
1615
from functools import cached_property
1716
from pathlib import Path
1817
from typing import TYPE_CHECKING
1918

20-
if sys.version_info >= (3, 11):
21-
import tomllib
22-
else:
23-
import tomli as tomllib
24-
2519
from packaging.requirements import Requirement
2620
from packaging.version import Version
2721

@@ -48,7 +42,8 @@ def min_dep(req: Requirement) -> Requirement:
4842
spec for spec in req.specifier if spec.operator in {"==", "~=", ">=", ">"}
4943
]
5044
if not filter_specs:
51-
return Requirement(req_name)
45+
# TODO: handle markers
46+
return Requirement(f"{req_name}{req.specifier}")
5247

5348
min_version = Version("0.0.0.a1")
5449
for spec in filter_specs:

docs/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ def setup(app: Sphinx):
203203
# -- Suppress link warnings ----------------------------------------------------
204204

205205
qualname_overrides = {
206+
"pathlib._local.Path": "pathlib.Path",
206207
"sklearn.neighbors._dist_metrics.DistanceMetric": "sklearn.metrics.DistanceMetric",
207208
"scanpy.plotting._matrixplot.MatrixPlot": "scanpy.pl.MatrixPlot",
208209
"scanpy.plotting._dotplot.DotPlot": "scanpy.pl.DotPlot",

docs/release-notes/3485.breaking.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Adopt the Scientific Python [deprecation schedule](https://scientific-python.org/specs/spec-0000/):
2+
remove Python 3.10 support and add Python 3.13 support, require anndata≥0.9 {smaller}`P Angerer`

hatch.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ overrides.matrix.deps.pre-install-commands = [
2525
{ if = [ "min" ], value = "uv run ci/scripts/min-deps.py pyproject.toml --all-extras -o ci/scanpy-min-deps.txt" },
2626
]
2727
overrides.matrix.deps.python = [
28-
{ if = [ "min" ], value = "3.10" },
29-
{ if = [ "stable", "full", "pre" ], value = "3.12" },
28+
{ if = [ "min" ], value = "3.11" },
29+
{ if = [ "stable", "full", "pre" ], value = "3.13" },
3030
]
3131
overrides.matrix.deps.features = [
3232
{ if = [ "full" ], value = "test-full" },

pyproject.toml

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ requires = [ "hatchling", "hatch-vcs" ]
55
[project]
66
name = "scanpy"
77
description = "Single-Cell Analysis in Python."
8-
requires-python = ">=3.10"
8+
requires-python = ">=3.11"
99
license = "BSD-3-clause"
1010
authors = [
1111
{ name = "Alex Wolf" },
@@ -39,29 +39,29 @@ classifiers = [
3939
"Operating System :: Microsoft :: Windows",
4040
"Operating System :: POSIX :: Linux",
4141
"Programming Language :: Python :: 3",
42-
"Programming Language :: Python :: 3.10",
4342
"Programming Language :: Python :: 3.11",
4443
"Programming Language :: Python :: 3.12",
44+
"Programming Language :: Python :: 3.13",
4545
"Topic :: Scientific/Engineering :: Bio-Informatics",
4646
"Topic :: Scientific/Engineering :: Visualization",
4747
]
4848
dependencies = [
49-
"anndata>=0.8",
50-
"numpy>=1.24",
49+
"anndata>=0.9",
50+
"numpy>=1.25",
5151
"matplotlib>=3.6",
52-
"pandas >=1.5",
53-
"scipy>=1.8",
52+
"pandas >=2.0",
53+
"scipy>=1.11",
5454
"seaborn>=0.13",
55-
"h5py>=3.7",
55+
"h5py>=3.8",
5656
"tqdm",
57-
"scikit-learn>=1.1,<1.6.0",
57+
"scikit-learn>=1.1,<1.6",
5858
"statsmodels>=0.13",
5959
"patsy!=1.0.0", # https://github.com/pydata/patsy/issues/215
60-
"networkx>=2.7",
60+
"networkx>=2.8",
6161
"natsort",
6262
"joblib",
63-
"numba>=0.57",
64-
"umap-learn>=0.5,!=0.5.0",
63+
"numba>=0.58",
64+
"umap-learn>=0.5,!=0.5",
6565
"pynndescent>=0.5",
6666
"packaging>=21.3",
6767
"session-info2",
@@ -146,10 +146,10 @@ magic = [ "magic-impute>=2.0" ] # MAGIC imputation method
146146
skmisc = [ "scikit-misc>=0.1.3" ] # highly_variable_genes method 'seurat_v3'
147147
harmony = [ "harmonypy" ] # Harmony dataset integration
148148
scanorama = [ "scanorama" ] # Scanorama dataset integration
149-
scrublet = [ "scikit-image" ] # Doublet detection with automatic thresholds
149+
scrublet = [ "scikit-image>=0.20" ] # Doublet detection with automatic thresholds
150150
# Acceleration
151151
rapids = [ "cudf>=0.9", "cuml>=0.9", "cugraph>=0.9" ] # GPU accelerated calculation of neighbors
152-
dask = [ "dask[array]>=2022.09.2,<2024.8.0" ] # Use the Dask parallelization engine
152+
dask = [ "dask[array]>=2023.5.1,<2024.8.0" ] # Use the Dask parallelization engine
153153
dask-ml = [ "dask-ml", "scanpy[dask]" ] # Dask-ML for sklearn-like API
154154

155155
[tool.hatch.build.targets.wheel]

src/scanpy/_compat.py

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
from __future__ import annotations
22

3-
import os
43
import sys
54
import warnings
6-
from dataclasses import dataclass, field
75
from functools import WRAPPER_ASSIGNMENTS, cache, partial, wraps
86
from importlib.util import find_spec
9-
from pathlib import Path
107
from typing import TYPE_CHECKING, Literal, ParamSpec, TypeVar, cast, overload
118

129
import numpy as np
@@ -63,25 +60,6 @@ def fullname(typ: type) -> str:
6360
return f"{module}.{name}"
6461

6562

66-
if sys.version_info >= (3, 11):
67-
from contextlib import chdir
68-
else:
69-
import os
70-
from contextlib import AbstractContextManager
71-
72-
@dataclass
73-
class chdir(AbstractContextManager):
74-
path: Path
75-
_old_cwd: list[Path] = field(default_factory=list)
76-
77-
def __enter__(self) -> None:
78-
self._old_cwd.append(Path.cwd())
79-
os.chdir(self.path)
80-
81-
def __exit__(self, *_excinfo) -> None:
82-
os.chdir(self._old_cwd.pop())
83-
84-
8563
def pkg_metadata(package: str) -> PackageMetadata:
8664
from importlib.metadata import metadata
8765

@@ -106,18 +84,6 @@ def old_positionals(*old_positionals: str):
10684
return lambda func: func
10785

10886

109-
if sys.version_info >= (3, 11):
110-
111-
def add_note(exc: BaseException, note: str) -> None:
112-
exc.add_note(note)
113-
else:
114-
115-
def add_note(exc: BaseException, note: str) -> None:
116-
if not hasattr(exc, "__notes__"):
117-
exc.__notes__ = []
118-
exc.__notes__.append(note)
119-
120-
12187
if sys.version_info >= (3, 13):
12288
from warnings import deprecated as _deprecated
12389
else:

0 commit comments

Comments
 (0)