Skip to content

[0.4.0] add support for Needleman-Wunsch with scores; update Python version support#23

Merged
andrew-titus merged 21 commits intomainfrom
nw-scores
Apr 13, 2026
Merged

[0.4.0] add support for Needleman-Wunsch with scores; update Python version support#23
andrew-titus merged 21 commits intomainfrom
nw-scores

Conversation

@andrew-titus
Copy link
Copy Markdown
Collaborator

@andrew-titus andrew-titus commented Apr 6, 2026

Summary

  • New feature: needleman_wunsch_with_scores() supporting custom pairwise scoring functions (score_fn(a, b) -> float) for alignment with continuous similarity measures (e.g., spatial proximity, text edit distance, character overlap) instead of binary match/mismatch.
  • Dependency upgrades: Upgrade PyO3 from 0.20 to 0.28 (with Bound API migration) and stable ABI minimum from Python 3.7 to 3.10. Update Python version support to 3.10-3.14 (drop 3.9, add 3.14).
  • Lint modernization: Replace legacy linting toolchain (black, flake8, isort, pylint, pydocstyle, bandit) with ruff and mypy. Give each linter its own --run-only-* flag in scripts/lint.sh.
  • Rust refactor: Extract shared needleman_wunsch_core helper parameterized by a scoring closure, eliminating code duplication between standard and score-matrix NW variants (zero runtime cost via monomorphization).
  • Testing: Add 10 unit tests for needleman_wunsch_with_scores and performance benchmarks (runtime + memory) using a char-overlap scoring function.
  • Housekeeping: Remove legacy config files (.pylintrc, .pydocstyle, .pydocstyle_test, .coveragerc, setup.cfg, mypy.ini); all configuration now in pyproject.toml. Add CHANGELOG.md with full version history.

Test plan

  • All 32 unit tests pass (pytest tests/unit -v)
  • Performance tests pass locally (pytest tests/perf -v)
  • Lint passes (./scripts/lint.sh)
  • Individual lint flags work (e.g., ./scripts/lint.sh --run-only-ruff-check)
  • CI tests and lint pass on all Python versions (3.10-3.14)
  • Wheel builds succeed across platforms (post-merge, unfortunately)

🤖 Generated with Claude Code

Drew Titus and others added 15 commits April 6, 2026 12:26
…ersion support

Add needleman_wunsch_with_scores() function that accepts a custom pairwise scoring
function (score_fn: Callable[[T, T], float]) instead of flat match/mismatch scores,
enabling continuous similarity measures for applications like OCR text alignment.

Also updates Python version support to 3.10-3.14 (dropping EOL 3.9, adding 3.14),
adds CHANGELOG.md with full release history, and updates documentation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace black, flake8, isort, pylint, pydocstyle, and bandit with ruff (lint +
format) and mypy. All Python lint/format configuration is now consolidated in
pyproject.toml. Coverage config also moved from .coveragerc to pyproject.toml.

Removed: setup.cfg, .pylintrc, .pydocstyle, .pydocstyle_test, mypy.ini,
.coveragerc. CI lint matrix reduced from 5 jobs to 3 (fast-linters, mypy,
cargo-clippy).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two tests had wrong expected alignments:
- test_asymmetric_scores: expected alignment scored -3 but algorithm
  correctly finds alignment scoring 1
- test_scores_prefer_gaps_over_bad_match: expected a different
  tie-breaking path; updated to match diagonal > left > up priority

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- CHANGELOG: add Removed section for deleted legacy config files
- README: replace stale black badge with ruff, add Development section

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…pdate CHANGELOG

- Rust edition 2024 not yet supported by Maturin; revert to 2021.
- PyO3 0.28 handles extension-module automatically; remove from maturin config.
- Update CHANGELOG to reflect actual Cargo changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PyO3 0.28 removed the GIL-dependent &PyModule in favor of
&Bound<'_, PyModule> for #[pymodule] init functions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
abi3-py311 uses PyType_GetName which doesn't exist in Python 3.10,
causing ImportError on the lowest supported version.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- lint.sh: replace --run-only-fast-linters with individual flags for
  each linter (copyright-check, ruff-check, ruff-format, cargo-fmt)
- lib.rs: extract needleman_wunsch_core helper with closure-based
  scoring to eliminate duplication between NW and NW-with-score-matrix
- CHANGELOG: document both refactors

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comment thread rust/src/lib.rs
/// A Python module implemented in Rust.
#[pymodule]
fn _sequence_align(_py: Python, m: &PyModule) -> PyResult<()> {
fn _sequence_align(m: &Bound<'_, PyModule>) -> PyResult<()> {
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Note for reviewer -- this was required from an API change in pyo3

Drew Titus and others added 4 commits April 7, 2026 14:27
Uses char-overlap scoring function for a realistic continuous-similarity
benchmark. Runtime and memory thresholds calibrated on R5.4 instance.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@andrew-titus andrew-titus marked this pull request as ready for review April 7, 2026 14:54
Comment thread src/sequence_align/pairwise.py Outdated
Comment thread src/sequence_align/pairwise.py Outdated
AmieRamie
AmieRamie previously approved these changes Apr 9, 2026
Copy link
Copy Markdown

@AmieRamie AmieRamie left a comment

Choose a reason for hiding this comment

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

Just had some NIT's, otherwise LGTM

Comment thread src/sequence_align/pairwise.py Outdated
Copy link
Copy Markdown

@libinliang866 libinliang866 left a comment

Choose a reason for hiding this comment

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

Hi Drew — sorry for the late review. I just noticed the request in my personal email. I’ve left one small question regarding the default value of gap; otherwise, everything looks good to me. Hope you’re feeling better soon.

Copy link
Copy Markdown

@AmieRamie AmieRamie left a comment

Choose a reason for hiding this comment

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

LGTM!

@andrew-titus andrew-titus merged commit 64a0cca into main Apr 13, 2026
11 checks passed
@andrew-titus andrew-titus deleted the nw-scores branch April 13, 2026 15:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants