diff --git a/.github/requirements-3.10.txt b/.github/requirements-3.10.txt index 986ca9e..33faa80 100644 --- a/.github/requirements-3.10.txt +++ b/.github/requirements-3.10.txt @@ -8,7 +8,7 @@ cycler==0.12.1 # via matplotlib exceptiongroup==1.2.2 # via pytest -fonttools==4.55.3 +fonttools==4.56.0 # via matplotlib gemmi==0.7.0 # via -r tests/requirements.in @@ -16,13 +16,13 @@ iniconfig==2.0.0 # via pytest kiwisolver==1.4.8 # via matplotlib -matplotlib==3.10.0 +matplotlib==3.10.1 # via ase more-itertools==10.6.0 - # via parsnip (pyproject.toml) -numpy==2.2.1 + # via parsnip-cif (pyproject.toml) +numpy==2.2.3 # via - # parsnip (pyproject.toml) + # parsnip-cif (pyproject.toml) # ase # contourpy # matplotlib @@ -43,15 +43,15 @@ pycifrw==4.4.6 # via -r tests/requirements.in pyparsing==3.2.1 # via matplotlib -pytest==8.3.4 +pytest==8.3.5 # via # -r tests/requirements.in # pytest-doctestplus -pytest-doctestplus==1.3.0 +pytest-doctestplus==1.4.0 # via -r tests/requirements.in python-dateutil==2.9.0.post0 # via matplotlib -scipy==1.15.1 +scipy==1.15.2 # via ase six==1.17.0 # via python-dateutil diff --git a/.github/requirements-3.11.txt b/.github/requirements-3.11.txt index 4d1b928..e2c1997 100644 --- a/.github/requirements-3.11.txt +++ b/.github/requirements-3.11.txt @@ -6,7 +6,7 @@ contourpy==1.3.1 # via matplotlib cycler==0.12.1 # via matplotlib -fonttools==4.55.3 +fonttools==4.56.0 # via matplotlib gemmi==0.7.0 # via -r tests/requirements.in @@ -14,13 +14,13 @@ iniconfig==2.0.0 # via pytest kiwisolver==1.4.8 # via matplotlib -matplotlib==3.10.0 +matplotlib==3.10.1 # via ase more-itertools==10.6.0 - # via parsnip (pyproject.toml) -numpy==2.2.1 + # via parsnip-cif (pyproject.toml) +numpy==2.2.3 # via - # parsnip (pyproject.toml) + # parsnip-cif (pyproject.toml) # ase # contourpy # matplotlib @@ -41,15 +41,15 @@ pycifrw==4.4.6 # via -r tests/requirements.in pyparsing==3.2.1 # via matplotlib -pytest==8.3.4 +pytest==8.3.5 # via # -r tests/requirements.in # pytest-doctestplus -pytest-doctestplus==1.3.0 +pytest-doctestplus==1.4.0 # via -r tests/requirements.in python-dateutil==2.9.0.post0 # via matplotlib -scipy==1.15.1 +scipy==1.15.2 # via ase six==1.17.0 # via python-dateutil diff --git a/.github/requirements-3.12.txt b/.github/requirements-3.12.txt index 1fa3c12..1ce1414 100644 --- a/.github/requirements-3.12.txt +++ b/.github/requirements-3.12.txt @@ -6,7 +6,7 @@ contourpy==1.3.1 # via matplotlib cycler==0.12.1 # via matplotlib -fonttools==4.55.3 +fonttools==4.56.0 # via matplotlib gemmi==0.7.0 # via -r tests/requirements.in @@ -14,13 +14,13 @@ iniconfig==2.0.0 # via pytest kiwisolver==1.4.8 # via matplotlib -matplotlib==3.10.0 +matplotlib==3.10.1 # via ase more-itertools==10.6.0 - # via parsnip (pyproject.toml) -numpy==2.2.1 + # via parsnip-cif (pyproject.toml) +numpy==2.2.3 # via - # parsnip (pyproject.toml) + # parsnip-cif (pyproject.toml) # ase # contourpy # matplotlib @@ -41,15 +41,15 @@ pycifrw==4.4.6 # via -r tests/requirements.in pyparsing==3.2.1 # via matplotlib -pytest==8.3.4 +pytest==8.3.5 # via # -r tests/requirements.in # pytest-doctestplus -pytest-doctestplus==1.3.0 +pytest-doctestplus==1.4.0 # via -r tests/requirements.in python-dateutil==2.9.0.post0 # via matplotlib -scipy==1.15.1 +scipy==1.15.2 # via ase six==1.17.0 # via python-dateutil diff --git a/.github/requirements-3.13.txt b/.github/requirements-3.13.txt index aaab9da..edb13ea 100644 --- a/.github/requirements-3.13.txt +++ b/.github/requirements-3.13.txt @@ -6,7 +6,7 @@ contourpy==1.3.1 # via matplotlib cycler==0.12.1 # via matplotlib -fonttools==4.55.3 +fonttools==4.56.0 # via matplotlib gemmi==0.7.0 # via -r tests/requirements.in @@ -14,13 +14,13 @@ iniconfig==2.0.0 # via pytest kiwisolver==1.4.8 # via matplotlib -matplotlib==3.10.0 +matplotlib==3.10.1 # via ase more-itertools==10.6.0 - # via parsnip (pyproject.toml) -numpy==2.2.1 + # via parsnip-cif (pyproject.toml) +numpy==2.2.3 # via - # parsnip (pyproject.toml) + # parsnip-cif (pyproject.toml) # ase # contourpy # matplotlib @@ -41,15 +41,15 @@ pycifrw==4.4.6 # via -r tests/requirements.in pyparsing==3.2.1 # via matplotlib -pytest==8.3.4 +pytest==8.3.5 # via # -r tests/requirements.in # pytest-doctestplus -pytest-doctestplus==1.3.0 +pytest-doctestplus==1.4.0 # via -r tests/requirements.in python-dateutil==2.9.0.post0 # via matplotlib -scipy==1.15.1 +scipy==1.15.2 # via ase six==1.17.0 # via python-dateutil diff --git a/.github/requirements-3.9.txt b/.github/requirements-3.9.txt index 8ee932f..6a81d63 100644 --- a/.github/requirements-3.9.txt +++ b/.github/requirements-3.9.txt @@ -8,7 +8,7 @@ cycler==0.12.1 # via matplotlib exceptiongroup==1.2.2 # via pytest -fonttools==4.55.3 +fonttools==4.56.0 # via matplotlib gemmi==0.7.0 # via -r tests/requirements.in @@ -21,10 +21,10 @@ kiwisolver==1.4.7 matplotlib==3.9.4 # via ase more-itertools==10.6.0 - # via parsnip (pyproject.toml) + # via parsnip-cif (pyproject.toml) numpy==2.0.2 # via - # parsnip (pyproject.toml) + # parsnip-cif (pyproject.toml) # ase # contourpy # matplotlib @@ -45,11 +45,11 @@ pycifrw==4.4.6 # via -r tests/requirements.in pyparsing==3.2.1 # via matplotlib -pytest==8.3.4 +pytest==8.3.5 # via # -r tests/requirements.in # pytest-doctestplus -pytest-doctestplus==1.3.0 +pytest-doctestplus==1.4.0 # via -r tests/requirements.in python-dateutil==2.9.0.post0 # via matplotlib diff --git a/.github/workflows/CI.yaml b/.github/workflows/CI.yaml index 44b0824..c8a991b 100644 --- a/.github/workflows/CI.yaml +++ b/.github/workflows/CI.yaml @@ -15,6 +15,11 @@ jobs: matrix: python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] runs-on: ["ubuntu-latest"] + include: + - runs-on: "macos-latest" + python-version: "3.13" + - runs-on: "macos-latest" + python-version: "3.9" # Pull in the test script from run_tests and distribute python from matrix versions uses: ./.github/workflows/run_tests.yaml with: @@ -29,6 +34,22 @@ jobs: matrix: # Code works on py3.6, but type annotations are broken python-version: ["3.7", "3.8"] runs-on: ["ubuntu-20.04"] + include: + - runs-on: "macos-14" + python-version: "3.8" + uses: ./.github/workflows/run_tests.yaml + with: + python-version: ${{ matrix.python-version }} + runs-on: ${{ matrix.runs-on }} + requirements-file: ".github/requirements-${{ matrix.python-version }}.txt" + + run-tests-windows: + needs: run-tests-modern-python + strategy: + fail-fast: false + matrix: + python-version: ["3.7", "3.9", "3.13"] + runs-on: ["windows-latest"] uses: ./.github/workflows/run_tests.yaml with: python-version: ${{ matrix.python-version }} diff --git a/.github/workflows/run_tests.yaml b/.github/workflows/run_tests.yaml index 5db51c4..419bdef 100644 --- a/.github/workflows/run_tests.yaml +++ b/.github/workflows/run_tests.yaml @@ -18,20 +18,20 @@ jobs: runs-on: ${{ inputs.runs-on }} steps: - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: ${{ inputs.python-version }} - name: Install uv uses: astral-sh/setup-uv@v4 with: - python-version: ${{ inputs.python-version }} - version: "0.5.11" - - name: Set up environment with dependencies - run: | - uv venv && . .venv/bin/activate - echo PATH=$PATH >> $GITHUB_ENV + version: "0.6.6" + - name: Install package run: | + which python python --version - uv pip install . -r ${{ inputs.requirements-file }} -v + uv pip install . -r ${{ inputs.requirements-file }} -v --reinstall --system python -c "import parsnip; print('parsnip', parsnip.__version__)" + - name: Test with pytest - run: | - python -m pytest -v + run: python -m ${{ runner.os != 'Windows' && 'pytest' || 'pytest tests' }} -v diff --git a/.github/workflows/update-uv-lockfiles.sh b/.github/workflows/update-uv-lockfiles.sh new file mode 100755 index 0000000..e52abe2 --- /dev/null +++ b/.github/workflows/update-uv-lockfiles.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +for version in 3.{9..13}; do + uv pip compile --python-version="$version" pyproject.toml tests/requirements.in > ".github/requirements-$version.txt" +done diff --git a/changelog.rst b/changelog.rst index 41e1c29..1c5474a 100644 --- a/changelog.rst +++ b/changelog.rst @@ -12,6 +12,7 @@ Added - New ``additional_columns`` parameter for ``build_unit_cell`` that allows the return of atom site labels and similar data alongside unit cell positions. - Ensured consistent ordering of lattice positions returned from ``build_unit_cell``. +- CI testing on Windows and macOS Fixed ~~~~~ diff --git a/tests/conftest.py b/tests/conftest.py index b22e7a8..9ef1bd7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,6 +2,7 @@ from __future__ import annotations import os +import re from dataclasses import dataclass import numpy as np @@ -14,6 +15,10 @@ data_file_path = os.path.dirname(__file__) + "/sample_data/" +def _arrstrip(arr: np.ndarray, pattern: str): + return np.vectorize(lambda x: re.sub(pattern, "", x))(arr) + + @dataclass class CifData: filename: str diff --git a/tests/requirements.in b/tests/requirements.in index 1902320..ad3103c 100644 --- a/tests/requirements.in +++ b/tests/requirements.in @@ -1,5 +1,5 @@ ase gemmi -pycifrw +pycifrw<5.0.0 pytest pytest-doctestplus diff --git a/tests/test_patterns.py b/tests/test_patterns.py index 4fd6c99..93e4f46 100644 --- a/tests/test_patterns.py +++ b/tests/test_patterns.py @@ -206,7 +206,7 @@ def test_try_cast_to_numeric(s): def test_repr(cif_data): import re - repr = re.sub(r"[a-z\s]*", "", cif_data.file.__repr__().split(":")[1]).split(",") + repr = re.sub(r"[a-z\s]*", "", cif_data.file.__repr__().split(" : ")[1]).split(",") n_pairs, n_tabs = [int(i) for i in repr] assert n_pairs == len(cif_data.file.pairs) assert n_tabs == len(cif_data.file.loops) diff --git a/tests/test_table_reader.py b/tests/test_table_reader.py index 35df9ef..d12cea9 100644 --- a/tests/test_table_reader.py +++ b/tests/test_table_reader.py @@ -4,7 +4,7 @@ import pytest from ase.io import cif as asecif from CifFile import CifFile as pycifRW -from conftest import bad_cif, cif_files_mark +from conftest import _arrstrip, bad_cif, cif_files_mark from gemmi import cif from more_itertools import flatten @@ -34,7 +34,7 @@ def test_reads_all_keys(cif_data): loop = [pycif.true_case[key] for key in loop] parsnip_data = cif_data.file.get_from_loops(loop) gemmi_data = _gemmi_read_table(cif_data.filename, loop) - np.testing.assert_array_equal(parsnip_data, gemmi_data) + np.testing.assert_array_equal(parsnip_data, _arrstrip(gemmi_data, r"\r")) @cif_files_mark diff --git a/tests/test_unitcells.py b/tests/test_unitcells.py index 17c03bb..1088c84 100644 --- a/tests/test_unitcells.py +++ b/tests/test_unitcells.py @@ -1,4 +1,3 @@ -import re import warnings from contextlib import nullcontext @@ -6,7 +5,7 @@ import pytest from ase import io from ase.build import supercells -from conftest import box_keys, cif_files_mark +from conftest import _arrstrip, box_keys, cif_files_mark from gemmi import cif from more_itertools import flatten @@ -22,10 +21,6 @@ def _gemmi_read_keys(filename, keys, as_number=True): return np.array([file_block.find_value(key) for key in keys]) -def _arrstrip(arr: np.ndarray, pattern: str): - return np.vectorize(lambda x: re.sub(pattern, "", x))(arr) - - @cif_files_mark # TODO: test with conversions to numeric as well def test_read_wyckoff_positions(cif_data): if "PDB_4INS_head.cif" in cif_data.filename: