Skip to content

Commit 2f63e4d

Browse files
authored
github: Add workflow to test with the oldest compatible dependency versions (#45)
* Add a script to pin the oldest versions of dependencies * github: Add another workflow to run tests with the oldest compatible dependency versions * github: Fix duplicated job name * Update poetry.lock * tests: Fix repr tests on Linux Co-authored by: mshafer-NI <[email protected]>
1 parent 5eac1d2 commit 2f63e4d

File tree

9 files changed

+1728
-6
lines changed

9 files changed

+1728
-6
lines changed

.github/workflows/CI.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,12 @@ jobs:
1919
name: Run unit tests
2020
uses: ./.github/workflows/run_unit_tests.yml
2121
needs: [check_nitypes]
22+
run_unit_tests_oldest_deps:
23+
name: Run unit tests (oldest deps)
24+
uses: ./.github/workflows/run_unit_tests_oldest_deps.yml
25+
needs: [check_nitypes]
2226
report_test_results:
2327
name: Report test results
2428
uses: ./.github/workflows/report_test_results.yml
25-
needs: [run_unit_tests]
29+
needs: [run_unit_tests, run_unit_tests_oldest_deps]
2630
if: always()

.github/workflows/run_unit_tests.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ jobs:
3232
key: nitypes-${{ runner.os }}-py${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('poetry.lock') }}
3333
- name: Install nitypes
3434
run: poetry install -v
35+
- name: Display installed dependency versions
36+
run: poetry run pip list
3537
- name: Run unit tests and code coverage
3638
run: poetry run pytest ./tests/unit -v --cov=nitypes --junitxml=test_results/nitypes-${{ matrix.os }}-py${{ matrix.python-version }}.xml
3739
- name: Upload test results
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
name: Run unit tests (oldest deps)
2+
3+
on:
4+
workflow_call:
5+
workflow_dispatch:
6+
7+
jobs:
8+
run_unit_tests_oldest_deps:
9+
name: Run unit tests (oldest deps)
10+
runs-on: ${{ matrix.os }}
11+
strategy:
12+
matrix:
13+
os: [windows-latest, ubuntu-latest]
14+
python-version: [3.9]
15+
# Fail-fast skews the pass/fail ratio and seems to make pytest produce
16+
# incomplete JUnit XML results.
17+
fail-fast: false
18+
steps:
19+
- name: Check out repo
20+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
21+
- name: Set up Python
22+
uses: ni/python-actions/setup-python@e8f25e9a64426bd431ac124b83df11b76cdf60d5 # v0.1.0
23+
id: setup-python
24+
with:
25+
python-version: ${{ matrix.python-version }}
26+
- name: Set up Poetry
27+
uses: ni/python-actions/setup-poetry@e8f25e9a64426bd431ac124b83df11b76cdf60d5 # v0.1.0
28+
- name: Cache virtualenv
29+
id: cache-virtualenv
30+
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
31+
with:
32+
path: .venv
33+
key: nitypes-${{ runner.os }}-py${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('poetry.lock') }}
34+
- name: Install nitypes (latest deps)
35+
if: steps.cache-virtualenv.outputs.cache-hit != 'true'
36+
run: poetry install -v
37+
- name: Pin oldest compatible dependencies
38+
if: steps.cache-virtualenv.outputs.cache-hit != 'true'
39+
run: |
40+
poetry run python scripts/pin_oldest_deps.py pyproject.toml
41+
poetry lock --no-update
42+
- name: Install nitypes (oldest deps)
43+
if: steps.cache-virtualenv.outputs.cache-hit != 'true'
44+
run: poetry install -v
45+
- name: Display installed dependency versions
46+
run: poetry run pip list
47+
- name: Run unit tests and code coverage
48+
run: poetry run pytest ./tests/unit -v --cov=nitypes --junitxml=test_results/nitypes-oldest-deps-${{ matrix.os }}-py${{ matrix.python-version }}.xml
49+
- name: Upload test results
50+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
51+
with:
52+
name: test_results_unit_oldest_deps_${{ matrix.os }}_py${{ matrix.python-version }}
53+
path: ./test_results/*.xml
54+
if: always()

poetry.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

poetry.lock.orig

Lines changed: 1616 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pytest-doctestplus = ">=1.4"
3030
pytest-mock = ">=3.0"
3131
# Use an unreleased version of hightime for testing.
3232
hightime = { git = "https://github.com/ni/hightime.git" }
33+
tomlkit = ">=0.11.0"
3334

3435
[tool.poetry.group.docs]
3536
optional = true
@@ -55,7 +56,7 @@ requires = ["poetry>=1.2"]
5556
build-backend = "poetry.masonry.api"
5657

5758
[tool.mypy]
58-
files = "examples/,src/,tests/"
59+
files = "examples/,scripts/,src/,tests/"
5960
plugins = "numpy.typing.mypy_plugin"
6061
namespace_packages = true
6162
strict = true
@@ -66,4 +67,4 @@ skips = [
6667
]
6768

6869
[tool.pyright]
69-
include = ["src/", "tests/"]
70+
include = ["examples/", "scripts/", "src/", "tests/"]

scripts/pin_oldest_deps.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
"""Pin dependencies to the oldest compatible version for testing."""
2+
3+
from __future__ import annotations
4+
5+
import sys
6+
from pathlib import Path
7+
8+
import tomlkit
9+
from tomlkit.items import AbstractTable, Array
10+
11+
12+
def main(args: list[str]) -> int | str | None:
13+
"""Pin dependencies to the oldest compatible version for testing."""
14+
pyproject_path = Path(args.pop())
15+
if args:
16+
return f"Unsupported arguments: {args!r}"
17+
pyproject = tomlkit.loads(pyproject_path.read_text())
18+
poetry_deps = pyproject["tool"]["poetry"]["dependencies"] # type: ignore[index]
19+
assert isinstance(poetry_deps, AbstractTable)
20+
21+
for dep, value in poetry_deps.items():
22+
if dep == "python":
23+
continue
24+
if isinstance(value, str) and (
25+
value.startswith("^") or value.startswith("~") or value.startswith(">=")
26+
):
27+
poetry_deps[dep] = "==" + value.lstrip("^~>=")
28+
elif isinstance(value, Array):
29+
for constraint in value:
30+
if "version" in constraint and (
31+
constraint["version"].startswith("^")
32+
or constraint["version"].startswith("~")
33+
or constraint["version"].startswith(">=")
34+
):
35+
constraint["version"] = "==" + constraint["version"].lstrip("^~>=")
36+
37+
pyproject_path.write_text(tomlkit.dumps(pyproject))
38+
print("Updated pyproject.toml with pinned dependencies.")
39+
return None
40+
41+
42+
if __name__ == "__main__":
43+
sys.exit(main(sys.argv[1:]))

tests/unit/waveform/test_analog_waveform.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import datetime as dt
66
import itertools
77
import pickle
8+
import sys
89
import weakref
910
from typing import Any, SupportsIndex
1011

@@ -1751,7 +1752,7 @@ def test___different_value___equality___not_equal(
17511752
assert left != right
17521753

17531754

1754-
if Version(np.__version__) >= Version("2.0.0"):
1755+
if Version(np.__version__) >= Version("2.0.0") or sys.platform != "win32":
17551756
_NDARRAY_DTYPE_INT32 = ", dtype=int32"
17561757
else:
17571758
_NDARRAY_DTYPE_INT32 = ""

tests/unit/waveform/test_spectrum.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import copy
55
import itertools
66
import pickle
7+
import sys
78
import weakref
89
from typing import Any, SupportsIndex
910

@@ -1172,7 +1173,7 @@ def test___different_value___equality___not_equal(
11721173
assert left != right
11731174

11741175

1175-
if Version(np.__version__) >= Version("2.0.0"):
1176+
if Version(np.__version__) >= Version("2.0.0") or sys.platform != "win32":
11761177
_NDARRAY_DTYPE_INT32 = ", dtype=int32"
11771178
else:
11781179
_NDARRAY_DTYPE_INT32 = ""

0 commit comments

Comments
 (0)