Skip to content
Merged
55 changes: 47 additions & 8 deletions .github/workflows/wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ on:
- '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:
Expand All @@ -25,9 +34,9 @@ jobs:
include:
- os: ubuntu-latest
cibw_archs: "x86_64"
- os: macos-latest
- os: macos-14
cibw_archs: "x86_64"
- os: macos-latest
- os: macos-14
cibw_archs: "arm64"

steps:
Expand Down Expand Up @@ -122,7 +131,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
os: [ubuntu-latest, macos-14]
python-version: ['3.9', '3.10', '3.11', '3.12']

steps:
Expand All @@ -144,12 +153,17 @@ jobs:
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/ kalign --force-reinstall
pip install --find-links wheelhouse/ "${DIST_NAME}" --force-reinstall

# Check what got installed
echo "=== Checking installed packages ==="
pip list | grep kalign || true
pip list | grep -E 'kalign' || true

# Check the kalign module structure
echo "=== Checking kalign module ==="
Expand Down Expand Up @@ -209,6 +223,10 @@ jobs:
needs: [build_wheels, build_sdist, test_install]
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
Expand All @@ -218,9 +236,30 @@ jobs:
merge-multiple: true
path: dist/

- name: Publish to PyPI
- 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]
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.PYPI_API_TOKEN }}
packages_dir: dist/
password: ${{ secrets.TEST_PYPI_API_TOKEN }}
packages_dir: dist/
repository-url: https://test.pypi.org/legacy/
verbose: true
7 changes: 4 additions & 3 deletions README-python.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ For bioinformatics ecosystem integration:
```bash
pip install kalign[biopython] # + Biopython integration
pip install kalign[skbio] # + scikit-bio integration
pip install kalign[all] # Everything
pip install kalign[io] # I/O helpers with Biopython
pip install kalign[analysis] # + pandas + matplotlib analysis/visualization helpers
pip install kalign[all] # Biopython + scikit-bio + pandas + matplotlib
```

## Quick Start
Expand Down Expand Up @@ -66,7 +67,7 @@ ATCGATC-ATCG

- **[📖 Quick Start Guide](python-docs/python-quickstart.md)** - Get up and running in minutes
- **[🔧 API Reference](python-docs/python-api.md)** - Complete function documentation
- **[🌐 Ecosystem Integration](python-docs/python-ecosystem.md)** - Biopython, scikit-bio, pandas integration
- **[🌐 Ecosystem Integration](python-docs/python-ecosystem.md)** - Biopython, scikit-bio, pandas, and matplotlib integration
- **[⚡ Performance Tuning](python-docs/python-performance.md)** - Optimization and benchmarking
- **[🛠️ Troubleshooting Guide](python-docs/python-troubleshooting.md)** - Common issues and solutions

Expand Down Expand Up @@ -580,4 +581,4 @@ See the [LICENSE](../COPYING) file for details.

---

**Made with ❤️ by the Kalign community** | **Star ⭐ us on GitHub if you find Kalign useful!**
**Made with ❤️ by the Kalign community** | **Star ⭐ us on GitHub if you find Kalign useful!**
44 changes: 43 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,48 @@ cmake -DBUILD_PYTHON_MODULE=ON ..
make
```

### Cutting a New Python Release (PyPI)

This repo is set up to publish to PyPI from GitHub Actions on version tags (`v*`) via `.github/workflows/wheels.yml`.

1) Bump versions
- Update the Python package version in `pyproject.toml` (`[project].version`).
- Update the C/C++ library version in `CMakeLists.txt` (`KALIGN_LIBRARY_VERSION_{MAJOR,MINOR,PATCH}`).
- (Optional but recommended) Add an entry to `ChangeLog`.

2) Sanity check locally (recommended)
```bash
python -m venv .venv
source .venv/bin/activate
python -m pip install -U pip build twine
python -m build
twine check dist/*
```

3) Configure trusted publishing on PyPI
- Add this GitHub repo/workflow as a trusted publisher in the PyPI project settings.
- Configure it to match the workflow/environment used in `.github/workflows/wheels.yml` (environment `pypi`).

4) Tag and push
```bash
git tag vX.Y.Z
git push origin vX.Y.Z
```

That tag push triggers the wheel + sdist build, install tests, and then uploads to PyPI.

#### Testing publishing on TestPyPI (optional)

If you want to test the publishing pipeline without uploading to the real PyPI project, this repo also supports a manual TestPyPI publish:

1) Create a TestPyPI API token and add it as the GitHub secret `TEST_PYPI_API_TOKEN`.
2) Run the GitHub Actions workflow **Build Python Wheels** manually and set `publish_target = testpypi`.

To install from TestPyPI while resolving dependencies from PyPI:
```bash
pip install -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple <package-name>
```

## Performance

### Benchmark Results
Expand Down Expand Up @@ -326,4 +368,4 @@ Please cite Kalign in your publications:

## License

Kalign is licensed under the GNU General Public License v3.0. See [COPYING](COPYING) for details.
Kalign is licensed under the GNU General Public License v3.0. See [COPYING](COPYING) for details.
14 changes: 5 additions & 9 deletions pyproject.toml
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested the version @etowahadams uploaded to the test-pypi server. I notice that biopython is listed as both a core depedency and an optional dependency. We likely want this dependency should be listed in one place or another, and not in both.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed! Now the only default dependencies are numpy, and the biopython is included as a optional dep

[project.optional-dependencies]
# Bioinformatics ecosystem integrations
biopython = ["biopython>=1.85"]
skbio = ["scikit-bio>=0.6.3"]
io = ["biopython>=1.85"]  # For I/O helper functions
analysis = ["pandas>=2.3.0", "matplotlib>=3.9.4"]
all = ["biopython>=1.85", "scikit-bio>=0.6.3", "pandas>=2.3.0", "matplotlib>=3.9.4"]

Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ build-backend = "scikit_build_core.build"
name = "kalign"
version = "3.4.5"
description = "Python wrapper for the Kalign multiple sequence alignment engine"
readme = "README.md"
license = {text = "GPL-3.0-or-later"}
readme = "README-python.md"
license = "GPL-3.0-or-later"
license-files = ["COPYING"]
authors = [
{name = "Timo Lassmann", email = "timo.lassmann@telethonkids.org.au"}
]
Expand All @@ -30,7 +31,6 @@ keywords = [
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
"Operating System :: OS Independent",
"Programming Language :: C",
"Programming Language :: C++",
Expand All @@ -46,12 +46,7 @@ classifiers = [
]
requires-python = ">=3.9"
dependencies = [
"biopython>=1.85",
"matplotlib>=3.9.4",
"numpy>=1.19.0",
"pandas>=2.3.0",
"rich>=14.0.0",
"scikit-bio>=0.6.3",
]

[project.scripts]
Expand All @@ -62,7 +57,8 @@ kalign = "kalign.cli:main"
biopython = ["biopython>=1.85"]
skbio = ["scikit-bio>=0.6.3"]
io = ["biopython>=1.85"] # For I/O helper functions
all = ["biopython>=1.85", "scikit-bio>=0.6.3"]
analysis = ["pandas>=2.3.0", "matplotlib>=3.9.4"]
all = ["biopython>=1.85", "scikit-bio>=0.6.3", "pandas>=2.3.0", "matplotlib>=3.9.4"]

# Development dependencies
dev = [
Expand Down
12 changes: 9 additions & 3 deletions python-docs/python-quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,13 @@ pip install kalign[biopython]
# For scikit-bio integration
pip install kalign[skbio]

# For everything
# For file I/O helpers (Biopython-backed)
pip install kalign[io]

# For pandas + matplotlib analysis/visualization helpers
pip install kalign[analysis]

# For all optional ecosystem integrations
pip install kalign[all]
```

Expand Down Expand Up @@ -597,7 +603,7 @@ aligned, stats, outliers = quality_control_alignment(sequences, ids)

Now that you're familiar with the basics, explore these advanced topics:

1. **[Ecosystem Integration Guide](python-ecosystem.md)** - Deep dive into Biopython and scikit-bio integration
1. **[Ecosystem Integration Guide](python-ecosystem.md)** - Deep dive into Biopython, scikit-bio, pandas, and matplotlib integration
2. **[Performance Tuning Guide](python-performance.md)** - Optimize for large-scale alignments
3. **[API Reference](python-api.md)** - Complete function documentation
4. **[Troubleshooting Guide](python-troubleshooting.md)** - Common issues and solutions
Expand All @@ -623,4 +629,4 @@ help(kalign.align)
help(kalign.utils.alignment_stats)
```

Happy aligning! 🧬✨
Happy aligning! 🧬✨
7 changes: 6 additions & 1 deletion python-kalign/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@

from . import _core, io, utils

__version__ = "3.4.5"
try:
from importlib.metadata import PackageNotFoundError, version as _dist_version

__version__ = _dist_version("kalign")
except Exception:
__version__ = "3.4.5"
__author__ = "Timo Lassmann"
__email__ = "timo.lassmann@telethonkids.org.au"

Expand Down
Loading