forked from scverse/anndata
-
Notifications
You must be signed in to change notification settings - Fork 0
/
conftest.py
104 lines (82 loc) · 3.5 KB
/
conftest.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# This file exists
# 1. to allow ignoring warnings without test collection failing on CI
# 2. as a pytest plugin/config that applies to doctests as well
# TODO: Fix that, e.g. with the `pytest -p anndata.testing._pytest` pattern.
from __future__ import annotations
import re
import warnings
from typing import TYPE_CHECKING, cast
import pytest
from anndata.compat import chdir
from anndata.utils import import_name
if TYPE_CHECKING:
from collections.abc import Generator, Iterable
from pathlib import Path
@pytest.fixture(autouse=True)
def _suppress_env_for_doctests(request: pytest.FixtureRequest) -> None:
if isinstance(request.node, pytest.DoctestItem):
request.getfixturevalue("_doctest_env")
@pytest.fixture()
def _doctest_env(
request: pytest.FixtureRequest, cache: pytest.Cache, tmp_path: Path
) -> Generator[None, None, None]:
from scanpy import settings
assert isinstance(request.node.parent, pytest.Module)
# request.node.parent is either a DoctestModule or a DoctestTextFile.
# Only DoctestModule has a .obj attribute (the imported module).
if request.node.parent.obj:
func = import_name(request.node.name)
warning_detail: tuple[type[Warning], str, bool] | None
if warning_detail := getattr(func, "__deprecated", None):
cat, msg, _ = warning_detail
warnings.filterwarnings("ignore", category=cat, message=re.escape(msg))
old_dd, settings.datasetdir = settings.datasetdir, cache.mkdir("scanpy-data")
with chdir(tmp_path):
yield
settings.datasetdir = old_dd
def pytest_itemcollected(item: pytest.Item) -> None:
"""Define behavior of pytest.mark.gpu."""
from importlib.util import find_spec
is_gpu = len([mark for mark in item.iter_markers(name="gpu")]) > 0
if is_gpu:
item.add_marker(
pytest.mark.skipif(not find_spec("cupy"), reason="Cupy not installed.")
)
def pytest_addoption(parser: pytest.Parser) -> None:
"""Hook to register custom CLI options and config values"""
parser.addoption(
"--strict-warnings",
action="store_true",
default=False,
help="Turn warnings into errors that are not overridden by `filterwarnings` or `filterwarnings_when_strict`.",
)
parser.addini(
"filterwarnings_when_strict",
"Filters to apply after `-Werror` when --strict-warnings is active",
type="linelist",
default=[],
)
def pytest_collection_modifyitems(
session: pytest.Session, config: pytest.Config, items: Iterable[pytest.Item]
):
if not config.getoption("--strict-warnings"):
return
warning_filters = [
"error",
*_config_get_strlist(config, "filterwarnings"),
*_config_get_strlist(config, "filterwarnings_when_strict"),
]
warning_marks = [pytest.mark.filterwarnings(f) for f in warning_filters]
# Add warning filters defined in the config to all tests items.
# Test items might already have @pytest.mark.filterwarnings applied,
# so we prepend ours to ensure that an item’s explicit filters override these.
# Reversing then individually prepending ensures that the order is preserved.
for item in items:
for mark in reversed(warning_marks):
item.add_marker(mark, append=False)
def _config_get_strlist(config: pytest.Config, name: str) -> list[str]:
if strs := config.getini(name):
assert isinstance(strs, list)
assert all(isinstance(item, str) for item in strs)
return cast(list[str], strs)
return []