Skip to content

Bump version to 3.5.1 for PyPI re-release #62

Bump version to 3.5.1 for PyPI re-release

Bump version to 3.5.1 for PyPI re-release #62

Workflow file for this run

name: Build Python Wheels
on:
push:
branches: [ main, python ]
tags:
- 'v*'
pull_request:
branches: [ main ]
paths:
- 'python-kalign/**'
- 'lib/**'
- 'CMakeLists.txt'
- 'pyproject.toml'
- '.github/workflows/wheels.yml'
workflow_dispatch:
inputs:
publish_target:
description: "Publish target (manual runs only)"
required: true
default: "none"
type: choice
options:
- none
- testpypi
jobs:
build_wheels:
name: Build wheels on ${{ matrix.os }} (${{ matrix.cibw_archs }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
cibw_archs: "x86_64"
- os: macos-14
cibw_archs: "x86_64"
- os: macos-14
cibw_archs: "arm64"
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install cibuildwheel build
- name: Build wheels
env:
CIBW_BUILD: cp39-* cp310-* cp311-* cp312-* cp313-*
CIBW_SKIP: "*-win32 *-manylinux_i686 *-musllinux*"
CIBW_ARCHS: ${{ matrix.cibw_archs }}
# Set minimum macOS version to match OpenMP requirements
CIBW_ENVIRONMENT_MACOS: >
CMAKE_BUILD_PARALLEL_LEVEL=2
OMP_NUM_THREADS=1
MACOSX_DEPLOYMENT_TARGET=14.0
CMAKE_OSX_DEPLOYMENT_TARGET=14.0
# Linux specific settings - handle different package managers
CIBW_BEFORE_ALL_LINUX: >
(yum install -y cmake3) ||
(apt-get update && apt-get install -y cmake) ||
(apk add --no-cache cmake)
CIBW_REPAIR_WHEEL_COMMAND_LINUX: auditwheel repair -w {dest_dir} {wheel}
# macOS specific settings
CIBW_BEFORE_ALL_MACOS: |
brew install --formula cmake libomp || echo "Dependencies may already be installed"
CIBW_REPAIR_WHEEL_COMMAND_MACOS: >
delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel}
# Environment variables for builds
CIBW_ENVIRONMENT: >
CMAKE_BUILD_PARALLEL_LEVEL=2
OMP_NUM_THREADS=1
# Skip testing during wheel build to avoid cross-compilation issues
CIBW_TEST_SKIP: "*"
run: |
python -m cibuildwheel --output-dir wheelhouse
- name: Upload wheels
uses: actions/upload-artifact@v4
with:
name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}
path: wheelhouse/*.whl
build_sdist:
name: Build source distribution
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install build
- name: Build sdist
run: |
python -m build --sdist --outdir dist/
- name: Upload sdist
uses: actions/upload-artifact@v4
with:
name: cibw-sdist
path: dist/*.tar.gz
test_install:
name: Test wheel installation
needs: [build_wheels]
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-14]
python-version: ['3.9', '3.10', '3.11', '3.12']
steps:
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Download wheels
uses: actions/download-artifact@v4
with:
pattern: cibw-wheels-*
merge-multiple: true
path: wheelhouse/
- name: Test installation and import
run: |
# Let pip find and install the appropriate wheel
echo "=== Available wheels ==="
ls -la wheelhouse/*.whl
# Determine the distribution name from the wheel filenames (PEP 427)
# e.g. kalign_test-3.4.5-...whl -> kalign-test
DIST_NAME="$(ls wheelhouse/*.whl | head -n 1 | xargs basename | cut -d- -f1 | tr '_' '-')"
echo "=== Detected dist name: ${DIST_NAME} ==="
echo "=== Installing wheel ==="
pip install --find-links wheelhouse/ "${DIST_NAME}" --force-reinstall
# Check what got installed
echo "=== Checking installed packages ==="
pip list | grep -E 'kalign' || true
# Check the kalign module structure
echo "=== Checking kalign module ==="
python -c "
import sys
print('Python version:', sys.version)
print('Attempting to import kalign...')
try:
import kalign
print('✓ kalign imported successfully')
print('kalign location:', kalign.__file__)
import os
kalign_dir = os.path.dirname(kalign.__file__)
print('kalign dir contents:', sorted(os.listdir(kalign_dir)))
# Check for _core specifically
core_files = [f for f in os.listdir(kalign_dir) if '_core' in f]
print('_core files found:', core_files)
except ImportError as e:
print('✗ Import failed:', str(e))
import os
import site
print('Site packages:', site.getsitepackages())
for site_dir in site.getsitepackages():
kalign_path = os.path.join(site_dir, 'kalign')
if os.path.exists(kalign_path):
print(f'Found kalign at {kalign_path}')
print('Contents:', sorted(os.listdir(kalign_path)))
break
sys.exit(1)
"
# Test the installation
python -c "
import kalign
print('kalign version:', kalign.__version__)
# Test basic functionality
sequences = ['ATCGATCG', 'ATCGTCG', 'ATCGATCG']
aligned = kalign.align(sequences, seq_type='dna')
print('Number of aligned sequences:', len(aligned))
print('Alignment lengths:', [len(seq) for seq in aligned])
assert len(aligned) == 3
assert all(len(seq) == len(aligned[0]) for seq in aligned)
print('✓ Basic alignment test passed')
# Test with different sequence types
protein_seqs = ['MKTAYIAKQRQ', 'MKTAYIAKQ', 'MKTAYIAK']
aligned_proteins = kalign.align(protein_seqs, seq_type='protein')
print('✓ Protein alignment test passed')
print('All tests passed successfully!')
"
test_ecosystem:
name: Test ecosystem integrations
needs: [build_wheels]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- uses: actions/download-artifact@v4
with:
pattern: cibw-wheels-*
merge-multiple: true
path: wheelhouse/
- name: Install kalign with all extras
run: |
DIST_NAME="$(ls wheelhouse/*.whl | head -n 1 | xargs basename | cut -d- -f1 | tr '_' '-')"
pip install --find-links wheelhouse/ "${DIST_NAME}[all]" --force-reinstall
pip install pytest
- name: Verify ecosystem packages are installed
run: |
python -c "import Bio; print(f'Biopython {Bio.__version__}')"
python -c "import skbio; print(f'scikit-bio {skbio.__version__}')"
python -c "import pandas; print(f'pandas {pandas.__version__}')"
python -c "import matplotlib; print(f'matplotlib {matplotlib.__version__}')"
- name: Run ecosystem tests (fail if any skipped)
run: |
pytest tests/python/test_ecosystem_real.py -v --tb=short 2>&1 | tee test_output.txt
# Fail if any tests were skipped — all ecosystem deps should be present
if grep -q "skipped" test_output.txt; then
echo "ERROR: Some ecosystem tests were skipped — all deps should be installed"
exit 1
fi
upload_pypi:
name: Upload to PyPI
needs: [build_wheels, build_sdist, test_install, test_ecosystem]
runs-on: ubuntu-latest
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
permissions:
id-token: write
environment:
name: pypi
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
pattern: cibw-*
merge-multiple: true
path: dist/
- name: Publish to PyPI (trusted publishing)
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages_dir: dist/
upload_testpypi:
name: Upload to TestPyPI
needs: [build_wheels, build_sdist, test_install, test_ecosystem]
runs-on: ubuntu-latest
if: github.event_name == 'workflow_dispatch' && inputs.publish_target == 'testpypi'
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
pattern: cibw-*
merge-multiple: true
path: dist/
- name: Publish to TestPyPI (API token)
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: __token__
password: ${{ secrets.TEST_PYPI_API_TOKEN }}
packages_dir: dist/
repository-url: https://test.pypi.org/legacy/
verbose: true