Skip to content

Commit 664276d

Browse files
authored
Backport PR #4106 on branch 1.12.x (test: adapt to x/layers unification) (#4107)
1 parent a15112e commit 664276d

7 files changed

Lines changed: 57 additions & 11 deletions

File tree

src/scanpy/_utils/_doctests.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,20 @@ def decorator(func: F) -> F:
1313
return decorator
1414

1515

16-
def doctest_skip[F: Callable](reason: str) -> Callable[[F], F]:
17-
"""Mark function so doctest is skipped."""
16+
def doctest_skipif[F: Callable](
17+
condition: bool = True, # noqa: FBT001, FBT002
18+
/,
19+
*,
20+
reason: str,
21+
) -> Callable[[F], F]:
22+
"""Mark function so doctest is skipped (if `condition` is met)."""
1823
if not reason:
1924
msg = "reason must not be empty"
2025
raise ValueError(msg)
2126

2227
def decorator(func: F) -> F:
23-
func._doctest_skip_reason = reason
28+
if condition:
29+
func._doctest_skip_reason = reason
2430
return func
2531

2632
return decorator

src/scanpy/datasets/_datasets.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@
77
import numpy as np
88
import pandas as pd
99
from anndata import AnnData, OldFormatWarning
10+
from packaging.version import Version
1011

1112
from .. import _utils
12-
from .._compat import deprecated, old_positionals
13+
from .._compat import deprecated, old_positionals, pkg_version
1314
from .._settings import settings
14-
from .._utils._doctests import doctest_internet, doctest_needs
15+
from .._utils._doctests import doctest_internet, doctest_needs, doctest_skipif
1516
from ..readwrite import read, read_h5ad, read_visium
1617
from ._utils import check_datasetdir_exists
1718

@@ -54,6 +55,12 @@
5455
HERE = Path(__file__).parent
5556

5657

58+
_doctest_skipif_old_anndata = doctest_skipif(
59+
pkg_version("anndata") < Version("0.13.dev0"), reason="old anndata"
60+
)
61+
62+
63+
@_doctest_skipif_old_anndata
5764
@old_positionals(
5865
"n_variables", "n_centers", "cluster_std", "n_observations", "random_state"
5966
)
@@ -92,6 +99,7 @@ def blobs(
9299
>>> sc.datasets.blobs()
93100
AnnData object with n_obs × n_vars = 640 × 11
94101
obs: 'blobs'
102+
layers: None
95103
96104
"""
97105
import sklearn.datasets
@@ -106,6 +114,7 @@ def blobs(
106114
return AnnData(x, obs=dict(blobs=y.astype(str)))
107115

108116

117+
@_doctest_skipif_old_anndata
109118
@doctest_internet
110119
@check_datasetdir_exists
111120
def burczynski06() -> AnnData:
@@ -127,13 +136,15 @@ def burczynski06() -> AnnData:
127136
...
128137
AnnData object with n_obs × n_vars = 127 × 22283
129138
obs: 'groups'
139+
layers: None
130140
131141
"""
132142
filename = settings.datasetdir / "burczynski06/GDS1615_full.soft.gz"
133143
url = "https://exampledata.scverse.org/scanpy/GDS1615_full.soft.gz"
134144
return read(filename, backup_url=url)
135145

136146

147+
@_doctest_skipif_old_anndata
137148
def krumsiek11() -> AnnData:
138149
r"""Simulated myeloid progenitors :cite:p:`Krumsiek2011`.
139150
@@ -159,6 +170,7 @@ def krumsiek11() -> AnnData:
159170
AnnData object with n_obs × n_vars = 640 × 11
160171
obs: 'cell_type'
161172
uns: 'iroot', 'highlights'
173+
layers: None
162174
163175
""" # noqa: D401
164176
with settings.verbosity.override("error"): # suppress output...
@@ -176,6 +188,7 @@ def krumsiek11() -> AnnData:
176188
return adata
177189

178190

191+
@_doctest_skipif_old_anndata
179192
@doctest_internet
180193
@doctest_needs("openpyxl")
181194
@check_datasetdir_exists
@@ -203,6 +216,7 @@ def moignard15() -> AnnData:
203216
AnnData object with n_obs × n_vars = 3934 × 42
204217
obs: 'exp_groups'
205218
uns: 'iroot', 'exp_groups_colors'
219+
layers: None
206220
207221
"""
208222
filename = settings.datasetdir / "moignard15/nbt.3154-S3.xlsx"
@@ -236,6 +250,7 @@ def moignard15() -> AnnData:
236250
return adata
237251

238252

253+
@_doctest_skipif_old_anndata
239254
@doctest_internet
240255
@check_datasetdir_exists
241256
def paul15() -> AnnData:
@@ -257,6 +272,7 @@ def paul15() -> AnnData:
257272
AnnData object with n_obs × n_vars = 2730 × 3451
258273
obs: 'paul15_clusters'
259274
uns: 'iroot'
275+
layers: None
260276
261277
"""
262278
import h5py
@@ -296,6 +312,7 @@ def paul15() -> AnnData:
296312
return adata
297313

298314

315+
@_doctest_skipif_old_anndata
299316
def toggleswitch() -> AnnData:
300317
"""Simulated toggleswitch.
301318
@@ -315,6 +332,7 @@ def toggleswitch() -> AnnData:
315332
...
316333
AnnData object with n_obs × n_vars = 200 × 2
317334
uns: 'iroot'
335+
layers: None
318336
319337
""" # noqa: D401
320338
filename = HERE / "toggleswitch.txt"
@@ -323,6 +341,7 @@ def toggleswitch() -> AnnData:
323341
return adata
324342

325343

344+
@_doctest_skipif_old_anndata
326345
def pbmc68k_reduced() -> AnnData:
327346
r"""Subsampled and processed 68k PBMCs.
328347
@@ -353,11 +372,13 @@ def pbmc68k_reduced() -> AnnData:
353372
obsm: 'X_pca', 'X_umap'
354373
varm: 'PCs'
355374
obsp: 'connectivities', 'distances'
375+
layers: None
356376
357377
"""
358378
return read_h5ad(HERE / "10x_pbmc68k_reduced.h5ad")
359379

360380

381+
@_doctest_skipif_old_anndata
361382
@doctest_internet
362383
@check_datasetdir_exists
363384
def pbmc3k() -> AnnData:
@@ -402,6 +423,7 @@ def pbmc3k() -> AnnData:
402423
>>> sc.datasets.pbmc3k()
403424
AnnData object with n_obs × n_vars = 2700 × 32738
404425
var: 'gene_ids'
426+
layers: None
405427
406428
"""
407429
url = "https://exampledata.scverse.org/scanpy/pbmc3k_raw.h5ad"
@@ -411,6 +433,7 @@ def pbmc3k() -> AnnData:
411433
return adata
412434

413435

436+
@_doctest_skipif_old_anndata
414437
@doctest_internet
415438
@check_datasetdir_exists
416439
def pbmc3k_processed() -> AnnData:
@@ -442,6 +465,7 @@ def pbmc3k_processed() -> AnnData:
442465
obsm: 'X_pca', 'X_tsne', 'X_umap', 'X_draw_graph_fr'
443466
varm: 'PCs'
444467
obsp: 'distances', 'connectivities'
468+
layers: None
445469
446470
""" # noqa: D401
447471
url = "https://exampledata.scverse.org/scanpy/pbmc3k.h5ad"
@@ -509,6 +533,7 @@ def _download_visium_dataset(
509533

510534

511535
@deprecated("Use `squidpy.datasets.visium` instead.")
536+
@_doctest_skipif_old_anndata
512537
@doctest_internet
513538
@check_datasetdir_exists
514539
def visium_sge(
@@ -550,6 +575,7 @@ def visium_sge(
550575
var: 'gene_ids', 'feature_types', 'genome'
551576
uns: 'spatial'
552577
obsm: 'spatial'
578+
layers: None
553579
554580
""" # noqa: D401
555581
spaceranger_version = "1.1.0" if "V1_" in sample_id else "1.2.0"

src/scanpy/datasets/_ebi_expression_atlas.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from .._settings import settings
1515
from .._utils._doctests import doctest_internet
1616
from ..readwrite import _download
17+
from ._datasets import _doctest_skipif_old_anndata
1718
from ._utils import check_datasetdir_exists
1819

1920
if TYPE_CHECKING:
@@ -107,6 +108,7 @@ def read_expression_from_archive(archive: ZipFile) -> anndata.AnnData:
107108
return adata
108109

109110

111+
@_doctest_skipif_old_anndata
110112
@doctest_internet
111113
def ebi_expression_atlas(
112114
accession: str, *, filter_boring: bool = False
@@ -140,6 +142,7 @@ def ebi_expression_atlas(
140142
>>> sc.datasets.ebi_expression_atlas("E-MTAB-4888") # doctest: +ELLIPSIS
141143
AnnData object with n_obs × n_vars = 2261 × 23899
142144
obs: 'Sample Characteristic[organism]', 'Sample Characteristic Ontology Term[organism]', ..., 'Factor Value[cell type]', 'Factor Value Ontology Term[cell type]'
145+
layers: None
143146
144147
"""
145148
experiment_dir = settings.datasetdir / accession

src/scanpy/external/pp/_hashsolo.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939

4040
from ..._compat import old_positionals
4141
from ..._utils import check_nonnegative_integers
42-
from ..._utils._doctests import doctest_skip
42+
from ..._utils._doctests import doctest_skipif
4343

4444
if TYPE_CHECKING:
4545
from collections.abc import Sequence
@@ -295,7 +295,7 @@ def _calculate_bayes_rule(
295295
@old_positionals(
296296
"priors", "pre_existing_clusters", "number_of_noise_barcodes", "inplace"
297297
)
298-
@doctest_skip("Illustrative but not runnable doctest code")
298+
@doctest_skipif(reason="Illustrative but not runnable doctest code")
299299
def hashsolo(
300300
adata: AnnData,
301301
cell_hashing_columns: Sequence[str],

src/scanpy/tools/_ingest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from .._compat import CSBase, old_positionals
1212
from .._settings import settings
1313
from .._utils import NeighborsView, raise_not_implemented_error_if_backed_type
14-
from .._utils._doctests import doctest_skip
14+
from .._utils._doctests import doctest_skipif
1515
from ..neighbors import FlatTree
1616

1717
if TYPE_CHECKING:
@@ -30,7 +30,7 @@
3030
"neighbors_key",
3131
"inplace",
3232
)
33-
@doctest_skip("illustrative short example but not runnable")
33+
@doctest_skipif(reason="illustrative short example but not runnable")
3434
def ingest(
3535
adata: AnnData,
3636
adata_ref: AnnData,

src/testing/scanpy/_pytest/__init__.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@
1717
from collections.abc import Generator, Iterable, Mapping
1818

1919

20+
MARK_RETRY_DOWNLOAD = pytest.mark.flaky(
21+
reruns=5,
22+
reruns_delay=2,
23+
# The list of matches here probably needs to be expanded
24+
only_rerun=[r"ConnectionError", r"HTTPError"],
25+
)
26+
27+
2028
_original_settings: Mapping[str, object] | None = None
2129

2230

@@ -107,7 +115,7 @@ def pytest_collection_modifyitems(
107115
# `--run-internet` passed
108116
if "internet" in item.keywords:
109117
item.add_marker(skipif_not_run_internet)
110-
item.add_marker(pytest.mark.flaky(reruns=5, reruns_delay=2))
118+
item.add_marker(MARK_RETRY_DOWNLOAD)
111119

112120

113121
def _modify_doctests(request: pytest.FixtureRequest) -> None:
@@ -128,7 +136,7 @@ def _modify_doctests(request: pytest.FixtureRequest) -> None:
128136
if getattr(func, "_doctest_internet", False):
129137
if not request.config.getoption("--internet-tests"):
130138
pytest.skip(reason="need --internet-tests option to run")
131-
request.applymarker(pytest.mark.flaky(reruns=5, reruns_delay=2))
139+
request.applymarker(MARK_RETRY_DOWNLOAD)
132140

133141

134142
assert "scanpy" not in sys.modules, (

tests/test_datasets.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212
import numpy as np
1313
import pytest
1414
from anndata.tests.helpers import assert_adata_equal
15+
from packaging.version import Version
1516

1617
import scanpy as sc
18+
from scanpy._compat import pkg_version
1719
from testing.scanpy._helpers import data
1820
from testing.scanpy._pytest.marks import needs
1921

@@ -173,6 +175,7 @@ def test_download_failure() -> None:
173175
DS_MARKS = defaultdict(list, moignard15=[needs.openpyxl])
174176

175177

178+
@pytest.mark.skipif(pkg_version("anndata") < Version("0.13.dev0"), reason="old anndata")
176179
@pytest.mark.parametrize(
177180
"ds_name",
178181
[

0 commit comments

Comments
 (0)