Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test against mindeps #1314

Merged
merged 19 commits into from
Feb 16, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 28 additions & 9 deletions .azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ variables:
PIP_CACHE_DIR: $(Pipeline.Workspace)/.pip
RUN_COVERAGE: no
PYTEST_ADDOPTS: --color=yes --junitxml=test-data/test-results.xml
PRERELEASE_DEPENDENCIES: no
# PRERELEASE_DEPENDENCIES: no
DEPENDENCIES_VERSION: "latest"
TEST_TYPE: "standard"

jobs:
- job: PyTest
Expand All @@ -16,11 +18,16 @@ jobs:
Python3.11:
python.version: "3.11"
RUN_COVERAGE: yes
TEST_TYPE: "coverage"
Python3.9:
python.version: "3.9"
PreRelease:
python.version: "3.11"
PRERELEASE_DEPENDENCIES: yes
DEPENDENCIES_VERSION: "pre-release"
TEST_TYPE: "strict-warning"
MinDeps:
python.version: "3.9"
DEPENDENCIES_VERSION: "minimum"
steps:
- task: UsePythonVersion@0
inputs:
Expand All @@ -40,13 +47,20 @@ jobs:
python -m pip install --upgrade pip wheel
pip install .[dev,test]
displayName: "Install dependencies"
condition: eq(variables['PRERELEASE_DEPENDENCIES'], 'no')
condition: eq(variables['DEPENDENCIES_VERSION'], 'latest')

- script: |
python -m pip install pip wheel tomli packaging
pip install `python3 ci/scripts/min-deps.py pyproject.toml --extra dev test`
pip install --no-deps .
displayName: "Install minimum dependencies"
condition: eq(variables['DEPENDENCIES_VERSION'], 'minimum')

- script: |
python -m pip install --pre --upgrade pip wheel
pip install --pre .[dev,test]
displayName: "Install dependencies release candidates"
condition: eq(variables['PRERELEASE_DEPENDENCIES'], 'yes')
condition: eq(variables['DEPENDENCIES_VERSION'], 'pre-release')

- script: |
pip list
Expand All @@ -55,23 +69,27 @@ jobs:
- script: |
pytest
displayName: "PyTest"
condition: and(eq(variables['RUN_COVERAGE'], 'no'), eq(variables['PRERELEASE_DEPENDENCIES'], 'no'))
condition: eq(variables['TEST_TYPE'], 'standard')
# and(eq(variables['RUN_COVERAGE'], 'no'), eq(variables['PRERELEASE_DEPENDENCIES'], 'no'))

- script: |
pytest --cov --cov-report=xml --cov-context=test
displayName: "PyTest (coverage)"
condition: and(eq(variables['RUN_COVERAGE'], 'yes'), eq(variables['PRERELEASE_DEPENDENCIES'], 'no'))
condition: eq(variables['TEST_TYPE'], 'coverage')
# condition: and(eq(variables['RUN_COVERAGE'], 'yes'), eq(variables['PRERELEASE_DEPENDENCIES'], 'no'))

- script: |
pytest --strict-warnings
displayName: "PyTest (treat warnings as errors)"
condition: and(eq(variables['RUN_COVERAGE'], 'no'), eq(variables['PRERELEASE_DEPENDENCIES'], 'yes'))
condition: eq(variables['TEST_TYPE'], 'strict-warning')
# condition: and(eq(variables['RUN_COVERAGE'], 'no'), eq(variables['PRERELEASE_DEPENDENCIES'], 'yes'))

- task: PublishCodeCoverageResults@1
inputs:
codeCoverageTool: Cobertura
summaryFileLocation: "test-data/coverage.xml"
condition: eq(variables['RUN_COVERAGE'], 'yes')
condition: eq(variables['TEST_TYPE'], 'coverage')
# eq(variables['RUN_COVERAGE'], 'yes')

- task: PublishTestResults@2
condition: succeededOrFailed()
Expand All @@ -82,7 +100,8 @@ jobs:

- script: bash <(curl -s https://codecov.io/bash)
displayName: "Upload to codecov.io"
condition: eq(variables['RUN_COVERAGE'], 'yes')
condition: eq(variables['TEST_TYPE'], 'coverage')
# eq(variables['RUN_COVERAGE'], 'yes')

- job: CheckBuild
pool:
Expand Down
72 changes: 72 additions & 0 deletions ci/scripts/min-deps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!python3
from __future__ import annotations

import argparse
from pathlib import Path

import tomli
from packaging.requirements import Requirement
from packaging.version import Version


def min_dep(req: Requirement) -> str:
"""
Given a requirement, return the minimum version specifier.

Example
-------

>>> min_dep(Requirement("numpy>=1.0"))
"numpy==1.0"
"""
req_name = req.name
if req.extras:
req_name = f"{req_name}[{','.join(req.extras)}]"

# TODO: Should this be allowed?
if not req.specifier:
return req_name

min_version = Version("0.0.0.a1")
for spec in req.specifier:
if spec.operator in [">", ">=", "~-"]:
min_version = max(min_version, Version(spec.version))

# TODO: should this return `~=` or `==`?
return f"{req_name}=={min_version}.*"


def extract_min_deps(dependencies: list[str]) -> list[str]:
return [min_dep(Requirement(dep)) for dep in dependencies]


def main():
# TODO: Allow optional dependencies
parser = argparse.ArgumentParser(
prog="min-deps",
description="""Parse a pyproject.toml file and output a list of minimum dependencies.

Output is directly passable to `pip install`.""",
usage="pip install `python min-deps.py pyproject.toml`",
)
parser.add_argument(
"path", type=Path, help="pyproject.toml to parse minimum dependencies from"
)
parser.add_argument("--extras", type=str, nargs="*", help="extras to install")

args = parser.parse_args()

pyproject = tomli.loads(args.path.read_text())

deps = pyproject["project"]["dependencies"]

for extra in args.extras:
deps += pyproject["project"]["optional-dependencies"][extra]

min_deps = extract_min_deps(deps)

print(" ".join(min_deps))


if __name__ == "__main__":
main()
18 changes: 18 additions & 0 deletions ci/scripts/run-min-deps.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# conda deactivate

mamba env remove -yn anndata-min-deps-test
mamba create -yn anndata-min-deps-test "python=3.9"

PACKAGES=`python3 ci/scripts/min-deps.py pyproject.toml --extra dev test`

# conda activate anndata-min-deps-test
# conda run -n anndata-min-deps-test pip install cupy-cuda12x


echo Installing $PACKAGES
conda run -n anndata-min-deps-test pip install $PACKAGES
conda run -n anndata-min-deps-test pip install pytest-xdist # cupy-cuda12x
conda run -n anndata-min-deps-test pip install -e . --no-deps
conda run -n anndata-min-deps-test pytest -n auto

conda list -n anndata-min-deps-tests
17 changes: 8 additions & 9 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,15 @@ classifiers = [
"Topic :: Scientific/Engineering :: Visualization",
]
dependencies = [
# pandas <1.1.1 has pandas/issues/35446
# pandas <1.4 has pandas/issues/35446
# pandas 2.1.0rc0 has pandas/issues/54622
# pandas 2.1.2 has pandas/issues/52927
"pandas >=1.1.1, !=2.1.0rc0, !=2.1.2",
"numpy>=1.16.5", # required by pandas 1.x
"scipy>1.4",
"h5py>=3",
"pandas >=1.4, !=2.1.0rc0, !=2.1.2",
"numpy>=1.23",
"scipy>1.8",
"h5py>=3.1",
"exceptiongroup; python_version<'3.11'",
"natsort",
"packaging>=20",
"packaging>=20.0",
"array_api_compat",
]
dynamic = ["version"]
Expand Down Expand Up @@ -81,7 +80,7 @@ doc = [
]
test = [
"loompy>=3.0.5",
"pytest >=6.0",
"pytest>=7.3",
"pytest-cov>=2.10",
"zarr",
"matplotlib",
Expand All @@ -91,7 +90,7 @@ test = [
"boltons",
"scanpy",
"httpx", # For data downloading
"dask[array,distributed]",
"dask[array,distributed]>=2022.01",
"awkward>=2.3, !=2.5.2",
"pyarrow",
"pytest_memray",
Expand Down
Loading