Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
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
197 changes: 148 additions & 49 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,61 +1,160 @@
name: CI

on:
push:
schedule:
- cron: '0 0 1 * *'
pull_request:
workflow_dispatch:
schedule:
- cron: "0 0 1 * *"

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
ci:
lint:
name: Ruff
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Install uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
version: "0.12.2"
python-version: "3.14"
enable-cache: true

- name: Ruff
run: uvx ruff@0.7.1 check

test:
name: Test (${{ matrix.os }}, Python ${{ matrix.python-version }})
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-2022, macos-13, macos-14]
python-version: ["3.10", "3.11", "3.12", "3.13"]
os: [ubuntu-latest, windows-2022, macos-15-intel, macos-15]
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
runs-on: ${{ matrix.os }}
timeout-minutes: 30
env:
UV_PYTHON: ${{ matrix.python-version }}
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Install uv and Python ${{ matrix.python-version }}
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
version: "0.12.2"
python-version: ${{ matrix.python-version }}
enable-cache: true
cache-suffix: ${{ matrix.os }}-${{ matrix.python-version }}

- name: Install core test dependencies
run: uv sync --frozen --extra dev

- name: Run the canonical core suite
run: uv run --frozen --no-sync python tests/test.py

- name: Install optional dependencies
run: uv sync --frozen --all-extras

- name: Run the optional BGEN suite
run: uv run --frozen --no-sync pytest pysnptools/distreader/test_bgen2.py

build:
name: Build distributions
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install the latest version of uv
uses: astral-sh/setup-uv@v3
- name: Install Python ${{ matrix.python-version }}
run: uv python install ${{ matrix.python-version }}


- name: Pinned Ruff
run: uvx ruff@0.7.1 check
- name: Lastest Ruff (just to check for warnings)
run: uvx ruff@latest check || echo "Ignoring warnings from the latest version of ruff"
- name: Install minimal dependencies
run: uv sync --extra dev
- name: Run min test
shell: bash
run: |
if [[ "$RUNNER_OS" != "Windows" ]]; then
source .venv/bin/activate
else
source .venv/Scripts/activate
fi
python tests/test.py
- name: Install all dependencies
run: uv sync --all-extras
- name: Run all tests
shell: bash
run: |
if [[ "$RUNNER_OS" != "Windows" ]]; then
source .venv/bin/activate
else
source .venv/Scripts/activate
fi
pytest pysnptools/distreader/test_bgen2.py

- name: Build
run: uv build
- name: Save SDist
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13'
uses: actions/upload-artifact@v4
with:
name: wheels
path: dist/*.tar.gz
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Install uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
version: "0.12.2"
python-version: "3.14"
enable-cache: true

- name: Build wheel and source distribution
run: uv build --no-sources

- name: Build wheel directly from the checkout
run: uv build --wheel --no-sources --out-dir direct-dist

- name: Compare direct and sdist-derived wheels
shell: bash
run: cmp dist/*.whl direct-dist/*.whl

- name: Upload distributions
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: distributions
path: |
dist/*.whl
dist/*.tar.gz
if-no-files-found: error
retention-days: 7

artifact-test:
name: Artifact test (${{ matrix.kind }}, Python ${{ matrix.python-version }})
needs: build
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
include:
- kind: wheel
python-version: "3.10"
package: dist/*.whl
- kind: sdist
python-version: "3.10"
package: dist/*.tar.gz
- kind: wheel
python-version: "3.14"
package: dist/*.whl
- kind: sdist
python-version: "3.14"
package: dist/*.tar.gz
steps:
- name: Install uv and Python ${{ matrix.python-version }}
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
version: "0.12.2"
python-version: ${{ matrix.python-version }}
no-project: true
enable-cache: false

- name: Download distributions
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: distributions
path: dist

- name: Create clean environment
run: uv venv --python ${{ matrix.python-version }} .artifact-venv

- name: Install exact ${{ matrix.kind }} artifact
run: uv pip install --python .artifact-venv/bin/python ${{ matrix.package }}

- name: Smoke-test installed package
run: >-
.artifact-venv/bin/python -c
"from importlib.resources import files;
import numpy as np;
import pysnptools;
from pysnptools.snpreader import SnpData;
data = SnpData(iid=[['a','a'],['b','b']], sid=['s1','s2'], val=np.array([[0.0,1.0],[2.0,1.0]]));
assert data.standardize().read().val.shape == (2,2);
manifests = ['pysnptools.hashdown.json','bgen.hashdown.json','synth.hashdown.json'];
assert all(files('pysnptools.util').joinpath(name).is_file() for name in manifests);
assert '.artifact-venv' in pysnptools.__file__;
print(pysnptools.__file__)"
150 changes: 150 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
name: Release

on:
push:
tags:
- "v*"

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false

jobs:
build:
name: Build and test distributions
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout tagged source
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Install uv and Python
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
version: "0.12.2"
python-version: "3.14"
enable-cache: true

- name: Verify tag and package version
env:
RELEASE_TAG: ${{ github.ref_name }}
run: >-
python -c
"import os, pathlib, tomllib;
version = tomllib.loads(pathlib.Path('pyproject.toml').read_text())['project']['version'];
expected = f'v{version}';
assert os.environ['RELEASE_TAG'] == expected,
f'tag {os.environ[\"RELEASE_TAG\"]!r} does not match package version {version!r}'"

- name: Verify the lockfile
run: uv lock --check

- name: Install all test dependencies
run: uv sync --frozen --all-extras

- name: Run the canonical core suite
run: uv run --frozen --no-sync python tests/test.py

- name: Run the optional BGEN suite
run: uv run --frozen --no-sync pytest pysnptools/distreader/test_bgen2.py

- name: Build wheel and source distribution
run: uv build --no-sources

- name: Build wheel directly from the checkout
run: uv build --wheel --no-sources --out-dir direct-dist

- name: Compare direct and sdist-derived wheels
run: cmp dist/*.whl direct-dist/*.whl

- name: Upload distributions
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: release-distributions
path: |
dist/*.whl
dist/*.tar.gz
if-no-files-found: error
retention-days: 14

artifact-test:
name: Test ${{ matrix.kind }} on Python ${{ matrix.python-version }}
needs: build
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
include:
- kind: wheel
python-version: "3.10"
package: dist/*.whl
- kind: sdist
python-version: "3.10"
package: dist/*.tar.gz
- kind: wheel
python-version: "3.14"
package: dist/*.whl
- kind: sdist
python-version: "3.14"
package: dist/*.tar.gz
steps:
- name: Install uv and Python ${{ matrix.python-version }}
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
version: "0.12.2"
python-version: ${{ matrix.python-version }}
no-project: true
enable-cache: false

- name: Download distributions
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: release-distributions
path: dist

- name: Create clean environment
run: uv venv --python ${{ matrix.python-version }} .artifact-venv

- name: Install exact ${{ matrix.kind }} artifact
run: uv pip install --python .artifact-venv/bin/python ${{ matrix.package }}

- name: Smoke-test installed package
run: >-
.artifact-venv/bin/python -c
"from importlib.resources import files;
import numpy as np;
import pysnptools;
from pysnptools.snpreader import SnpData;
data = SnpData(iid=[['a','a'],['b','b']], sid=['s1','s2'], val=np.array([[0.0,1.0],[2.0,1.0]]));
assert data.standardize().read().val.shape == (2,2);
manifests = ['pysnptools.hashdown.json','bgen.hashdown.json','synth.hashdown.json'];
assert all(files('pysnptools.util').joinpath(name).is_file() for name in manifests);
assert '.artifact-venv' in pysnptools.__file__;
print(pysnptools.__file__)"

publish:
name: Publish to PyPI
needs: artifact-test
runs-on: ubuntu-latest
timeout-minutes: 10
environment:
name: pypi
url: https://pypi.org/p/pysnptools
permissions:
id-token: write
steps:
- name: Download tested distributions
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: release-distributions
path: dist

- name: Publish distributions with Trusted Publishing
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
with:
packages-dir: dist/
attestations: true
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,3 @@ doc/ipynb/example2.dist.memmap
doc/ipynb/.ipynb_checkpoints/*
localcache*/*
peertopeer*/*
uv.lock
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.14
Loading