Skip to content

Commit 8354ec9

Browse files
committed
Add sanity-check tests for the declared dependencies
1 parent b75b333 commit 8354ec9

File tree

4 files changed

+82
-31
lines changed

4 files changed

+82
-31
lines changed

.github/workflows/main.yml

+5-28
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,10 @@ name: Basic tests
33
on: [push, pull_request]
44

55
jobs:
6-
build:
7-
6+
test:
87
runs-on: ubuntu-latest
9-
strategy:
10-
fail-fast: false
11-
matrix:
12-
python-version:
13-
- 3.5
14-
- 3.6
15-
- 3.7
16-
- 3.8
17-
- 3.9
18-
- pypy3
19-
- '3.10.0-rc.1 - 3.10.0'
20-
218
steps:
22-
- uses: actions/checkout@v2
23-
- name: Set up Python ${{ matrix.python-version }}
24-
uses: actions/setup-python@v2
25-
with:
26-
python-version: ${{ matrix.python-version }}
27-
- name: Upgrade pip and setuptools
28-
run: python -m pip install pip setuptools --upgrade
29-
- name: Install wheel
30-
if: matrix.python-version == '3.5'
31-
run: python -m pip install wheel
32-
- name: Install oldest-supported-numpy
33-
run: python -m pip install -v .
34-
- name: Check that numpy was installed
35-
run: python -c 'import numpy'
9+
- uses: actions/checkout@v2
10+
- uses: actions/setup-python@v2
11+
- run: pip install -r tests/requirements.txt
12+
- run: pytest

setup.cfg

+2-3
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,8 @@ version = 0.14
1818
[options]
1919
python_requires = >=3.5
2020
install_requires =
21-
# NOTE: platform_system 'AIX' and platform_machine 'aarch64' are mutually
22-
# exclusive so they are specified by themself when setting their
23-
# numpy version.
21+
# NOTE: Any platform-related assumptions made here are encoded in the
22+
# tests for this package.
2423

2524
# AIX requires fixes contained in numpy 1.16
2625
numpy==1.16.0; python_version=='3.5' and platform_system=='AIX'

tests/requirements.txt

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pytest
2+
packaging

tests/test_dependencies.py

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
"""Tests to ensure that the dependency declarations are sane.
2+
"""
3+
4+
import configparser
5+
import pprint
6+
from functools import cache
7+
from pathlib import Path
8+
9+
import pytest
10+
from packaging.requirements import Requirement
11+
12+
SETUP_CFG_FILE = Path(__file__).parent.parent / "setup.cfg"
13+
14+
15+
def is_pinned(requirement: Requirement) -> bool:
16+
return "==" in str(requirement.specifier)
17+
18+
19+
@cache
20+
def get_package_dependencies() -> list[Requirement]:
21+
"""A cached reader for getting dependencies of this package."""
22+
parser = configparser.ConfigParser()
23+
parser.read(SETUP_CFG_FILE)
24+
25+
return [
26+
Requirement(line)
27+
for line in parser.get("options", "install_requires").splitlines()
28+
if line
29+
]
30+
31+
32+
# The ordering of these markers is important, and is used in test names.
33+
# The tests, when run, look like: PyPy-3.6-Linux-aarch64` (bottom-first)
34+
@pytest.mark.parametrize("platform_machine", ["x86_64", "aarch64", "s390x", "arm64"])
35+
@pytest.mark.parametrize("platform_system", ["Linux", "Windows", "Darwin", "AIX"])
36+
@pytest.mark.parametrize("python_version", ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11"])
37+
@pytest.mark.parametrize("platform_python_implementation", ["CPython", "PyPy"])
38+
def test_has_at_most_one_pinned_dependency(
39+
platform_machine,
40+
platform_system,
41+
python_version,
42+
platform_python_implementation,
43+
):
44+
# These are known to be platforms that are not valid / possible at this time.
45+
if platform_system == "AIX":
46+
if platform_machine == "aarch64":
47+
pytest.skip("AIX and aarch64 are mutually exclusive.")
48+
if platform_python_implementation == "PyPy":
49+
pytest.skip("AIX and PyPy are mutually exclusive.")
50+
51+
if platform_python_implementation == "PyPy" and (platform_machine != "x86_64"):
52+
pytest.skip(f"PyPy is not supported on {platform_machine}.")
53+
54+
environment = {
55+
"python_version": python_version,
56+
"platform_python_implementation": platform_python_implementation,
57+
"platform_machine": platform_machine,
58+
"platform_system": platform_system,
59+
}
60+
61+
filtered_requirements = []
62+
for req in get_package_dependencies():
63+
assert req.marker
64+
if not req.marker.evaluate(environment):
65+
continue
66+
if not is_pinned(req):
67+
continue
68+
69+
filtered_requirements.append(req)
70+
71+
assert (
72+
len(filtered_requirements) <= 1
73+
), f"Expected no more than one pin.\n{pprint.pformat(environment)}"

0 commit comments

Comments
 (0)