seqpro 0.11.0__tar.gz → 0.12.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- seqpro-0.12.0/.github/workflows/bump.yaml +94 -0
- seqpro-0.12.0/.github/workflows/merge.yaml +50 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/.github/workflows/publish.yaml +52 -11
- seqpro-0.12.0/.github/workflows/release-pipeline.yaml +101 -0
- seqpro-0.12.0/.github/workflows/release.yaml +71 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/CHANGELOG.md +56 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/CLAUDE.md +4 -0
- seqpro-0.12.0/Cargo.lock +1497 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/Cargo.toml +9 -1
- {seqpro-0.11.0 → seqpro-0.12.0}/PKG-INFO +1 -1
- seqpro-0.12.0/benches/kshuffle.rs +30 -0
- seqpro-0.12.0/docs/superpowers/plans/2026-05-20-kshuffle-optimization.md +1102 -0
- seqpro-0.12.0/docs/superpowers/plans/2026-05-20-kshuffle-pooled-buffers-and-k2-fast-path.md +852 -0
- seqpro-0.12.0/docs/superpowers/plans/2026-05-20-kshuffle-wilson-single-pass.md +368 -0
- seqpro-0.12.0/docs/superpowers/plans/2026-05-20-release-pipeline.md +760 -0
- seqpro-0.12.0/docs/superpowers/plans/2026-05-28-translate-lut-validation.md +793 -0
- seqpro-0.12.0/docs/superpowers/specs/2026-05-20-kshuffle-optimization-design.md +161 -0
- seqpro-0.12.0/docs/superpowers/specs/2026-05-20-kshuffle-pooled-buffers-and-k2-fast-path-design.md +174 -0
- seqpro-0.12.0/docs/superpowers/specs/2026-05-20-kshuffle-wilson-single-pass-design.md +65 -0
- seqpro-0.12.0/docs/superpowers/specs/2026-05-20-release-pipeline-design.md +167 -0
- seqpro-0.12.0/docs/superpowers/specs/2026-05-28-translate-lut-and-validation-design.md +149 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/pixi.lock +9548 -7470
- {seqpro-0.11.0 → seqpro-0.12.0}/pixi.toml +11 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/pyproject.toml +1 -1
- {seqpro-0.11.0 → seqpro-0.12.0}/python/seqpro/_analyzers.py +9 -4
- {seqpro-0.11.0 → seqpro-0.12.0}/python/seqpro/_coords.py +5 -3
- seqpro-0.12.0/python/seqpro/_encoders.py +322 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/python/seqpro/_modifiers.py +8 -2
- {seqpro-0.11.0 → seqpro-0.12.0}/python/seqpro/_numba.py +57 -1
- {seqpro-0.11.0 → seqpro-0.12.0}/python/seqpro/_utils.py +3 -1
- {seqpro-0.11.0 → seqpro-0.12.0}/python/seqpro/alphabets/_alphabets.py +213 -92
- seqpro-0.12.0/skills/seqpro/SKILL.md +157 -0
- seqpro-0.12.0/src/kmer_encode.rs +88 -0
- seqpro-0.12.0/src/kshuffle.rs +630 -0
- seqpro-0.11.0/src/kshuffle.rs → seqpro-0.12.0/src/kshuffle_ref.rs +3 -36
- {seqpro-0.11.0 → seqpro-0.12.0}/src/lib.rs +8 -1
- seqpro-0.12.0/tests/_shape_fixtures.py +222 -0
- seqpro-0.12.0/tests/bench_translate_lut.py +60 -0
- seqpro-0.12.0/tests/conftest.py +0 -0
- seqpro-0.12.0/tests/test_encoders.py +44 -0
- seqpro-0.12.0/tests/test_ohe.py +185 -0
- seqpro-0.12.0/tests/test_shape_matrix.py +440 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/tests/test_tokenize.py +61 -0
- seqpro-0.12.0/tests/test_translate.py +449 -0
- seqpro-0.11.0/.github/workflows/bump.yaml +0 -49
- seqpro-0.11.0/.github/workflows/merge.yaml +0 -32
- seqpro-0.11.0/.github/workflows/release.yaml +0 -49
- seqpro-0.11.0/Cargo.lock +0 -598
- seqpro-0.11.0/python/seqpro/_encoders.py +0 -209
- seqpro-0.11.0/tests/test_ohe.py +0 -79
- seqpro-0.11.0/tests/test_translate.py +0 -167
- {seqpro-0.11.0 → seqpro-0.12.0}/.claude/skills/zensical-setup/.skillfish.json +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/.claude/skills/zensical-setup/SKILL.md +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/.gitattributes +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/.github/workflows/docs.yml +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/.github/workflows/lint.yaml +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/.github/workflows/test.yaml +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/.gitignore +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/.pre-commit-config.yaml +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/LICENSE +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/README.md +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/docs/api/alphabets.md +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/docs/api/bed.md +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/docs/api/gtf.md +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/docs/api/index.md +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/docs/api/ragged.md +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/docs/api/types.md +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/docs/index.md +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/docs/ragged.md +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/docs/superpowers/plans/2026-05-04-ragged-record-array.md +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/docs/superpowers/plans/2026-05-05-documentation-site.md +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/docs/superpowers/plans/2026-05-05-narwhals-coord-schema.md +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/docs/superpowers/plans/2026-05-05-ragged-zip-and-record-introspection.md +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/docs/superpowers/specs/2026-05-04-ragged-record-array-design.md +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/docs/superpowers/specs/2026-05-05-documentation-site-design.md +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/docs/superpowers/specs/2026-05-05-narwhals-coord-schema-design.md +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/docs/superpowers/specs/2026-05-05-ragged-zip-and-record-introspection-design.md +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/meta.yaml +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/python/seqpro/__init__.py +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/python/seqpro/_cleaners.py +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/python/seqpro/_types.py +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/python/seqpro/alphabets/__init__.py +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/python/seqpro/bed.py +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/python/seqpro/experimental/_experimental.py +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/python/seqpro/experimental/_visualizers.py +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/python/seqpro/gtf.py +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/python/seqpro/py.typed +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/python/seqpro/rag/__init__.py +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/python/seqpro/rag/_array.py +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/python/seqpro/rag/_gufuncs.py +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/python/seqpro/rag/_types.py +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/python/seqpro/rag/_utils.py +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/python/seqpro/transforms/__init__.py +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/python/seqpro/transforms/augmentation.py +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/python/seqpro/transforms/tmm.py +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/python/seqpro/xr/__init__.py +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/tests/bed/test_pyranges.py +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/tests/bed/test_read.py +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/tests/bed/test_sort.py +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/tests/bed/test_with_length.py +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/tests/test_analyzers.py +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/tests/test_coords.py +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/tests/test_modifiers.py +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/tests/test_ragged.py +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/tests/test_transforms.py +0 -0
- {seqpro-0.11.0 → seqpro-0.12.0}/zensical.toml +0 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
name: Bump version
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_call:
|
|
5
|
+
inputs:
|
|
6
|
+
increment:
|
|
7
|
+
description: "Force a specific bump (auto|PATCH|MINOR|MAJOR)"
|
|
8
|
+
type: string
|
|
9
|
+
required: false
|
|
10
|
+
default: "auto"
|
|
11
|
+
dry_run:
|
|
12
|
+
description: "Compute the bump but do not commit/push"
|
|
13
|
+
type: boolean
|
|
14
|
+
required: false
|
|
15
|
+
default: false
|
|
16
|
+
outputs:
|
|
17
|
+
tag:
|
|
18
|
+
description: "The version string after the bump (or projected version in dry-run)"
|
|
19
|
+
value: ${{ jobs.bump.outputs.tag }}
|
|
20
|
+
workflow_dispatch:
|
|
21
|
+
inputs:
|
|
22
|
+
increment:
|
|
23
|
+
description: "Force a specific bump"
|
|
24
|
+
type: choice
|
|
25
|
+
required: false
|
|
26
|
+
default: "auto"
|
|
27
|
+
options: ["auto", "PATCH", "MINOR", "MAJOR"]
|
|
28
|
+
dry_run:
|
|
29
|
+
description: "Compute the bump but do not commit/push"
|
|
30
|
+
type: boolean
|
|
31
|
+
required: false
|
|
32
|
+
default: false
|
|
33
|
+
|
|
34
|
+
jobs:
|
|
35
|
+
bump:
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
outputs:
|
|
38
|
+
tag: ${{ steps.emit.outputs.tag }}
|
|
39
|
+
steps:
|
|
40
|
+
- uses: actions/checkout@v4
|
|
41
|
+
with:
|
|
42
|
+
fetch-depth: 0
|
|
43
|
+
token: "${{ secrets.GH_TOKEN }}"
|
|
44
|
+
|
|
45
|
+
- name: Install commitizen
|
|
46
|
+
run: pip install commitizen --quiet
|
|
47
|
+
|
|
48
|
+
- name: Detect partial bump
|
|
49
|
+
id: detect
|
|
50
|
+
run: |
|
|
51
|
+
PROJECT_VERSION=$(cz version --project)
|
|
52
|
+
LATEST_TAG=$(git tag --sort=-version:refname | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | head -1)
|
|
53
|
+
if [ -n "$LATEST_TAG" ] && [ "$LATEST_TAG" != "$PROJECT_VERSION" ]; then
|
|
54
|
+
echo "partial=true" >> $GITHUB_OUTPUT
|
|
55
|
+
echo "tag=$LATEST_TAG" >> $GITHUB_OUTPUT
|
|
56
|
+
else
|
|
57
|
+
echo "partial=false" >> $GITHUB_OUTPUT
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
- name: Bump version (real)
|
|
61
|
+
if: steps.detect.outputs.partial != 'true' && inputs.dry_run == false
|
|
62
|
+
uses: commitizen-tools/commitizen-action@master
|
|
63
|
+
with:
|
|
64
|
+
github_token: ${{ secrets.GH_TOKEN }}
|
|
65
|
+
increment: ${{ inputs.increment != 'auto' && inputs.increment || '' }}
|
|
66
|
+
|
|
67
|
+
- name: Bump version (dry-run)
|
|
68
|
+
if: steps.detect.outputs.partial != 'true' && inputs.dry_run == true
|
|
69
|
+
run: |
|
|
70
|
+
ARGS="--dry-run --yes"
|
|
71
|
+
if [ "${{ inputs.increment }}" != "auto" ]; then
|
|
72
|
+
ARGS="$ARGS --increment ${{ inputs.increment }}"
|
|
73
|
+
fi
|
|
74
|
+
cz bump $ARGS
|
|
75
|
+
|
|
76
|
+
- name: Fix partial bump (tag exists on remote, update files only)
|
|
77
|
+
if: steps.detect.outputs.partial == 'true' && inputs.dry_run == false
|
|
78
|
+
run: |
|
|
79
|
+
git config user.name "github-actions[bot]"
|
|
80
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
81
|
+
NEW_VERSION="${{ steps.detect.outputs.tag }}"
|
|
82
|
+
cz bump --files-only --yes
|
|
83
|
+
BUMPED_VERSION=$(cz version --project)
|
|
84
|
+
git add pyproject.toml CHANGELOG.md
|
|
85
|
+
git commit -m "bump: version $NEW_VERSION"
|
|
86
|
+
git push origin main
|
|
87
|
+
git push origin "$BUMPED_VERSION"
|
|
88
|
+
|
|
89
|
+
- name: Emit resulting tag
|
|
90
|
+
id: emit
|
|
91
|
+
run: |
|
|
92
|
+
TAG=$(cz version --project)
|
|
93
|
+
echo "tag=$TAG" >> $GITHUB_OUTPUT
|
|
94
|
+
echo "Resolved tag: $TAG"
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
name: Merge main -> stable
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_call:
|
|
5
|
+
inputs:
|
|
6
|
+
dry_run:
|
|
7
|
+
description: 'Compute the rebase but do not push'
|
|
8
|
+
type: boolean
|
|
9
|
+
required: false
|
|
10
|
+
default: false
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
inputs:
|
|
13
|
+
dry_run:
|
|
14
|
+
description: 'Compute the rebase but do not push'
|
|
15
|
+
type: boolean
|
|
16
|
+
required: false
|
|
17
|
+
default: false
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
merge:
|
|
21
|
+
environment: pypi
|
|
22
|
+
permissions:
|
|
23
|
+
id-token: write
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
steps:
|
|
26
|
+
- name: Check out
|
|
27
|
+
uses: actions/checkout@v4
|
|
28
|
+
with:
|
|
29
|
+
ref: stable
|
|
30
|
+
fetch-depth: 0
|
|
31
|
+
token: "${{ secrets.GH_TOKEN }}"
|
|
32
|
+
- name: Config git
|
|
33
|
+
run: |
|
|
34
|
+
git config --global user.name "${GITHUB_ACTOR}"
|
|
35
|
+
git config --global user.email "${GITHUB_ACTOR}@users.noreply.github.com"
|
|
36
|
+
- name: Rebase stable onto main
|
|
37
|
+
run: git rebase origin/main
|
|
38
|
+
- name: Push to stable
|
|
39
|
+
if: inputs.dry_run == false
|
|
40
|
+
run: git push origin stable
|
|
41
|
+
- name: Dry-run summary (skipped push)
|
|
42
|
+
if: inputs.dry_run == true
|
|
43
|
+
run: |
|
|
44
|
+
{
|
|
45
|
+
echo "## Dry-run: would push the following to stable"
|
|
46
|
+
echo
|
|
47
|
+
echo '```'
|
|
48
|
+
git log --oneline origin/stable..HEAD
|
|
49
|
+
echo '```'
|
|
50
|
+
} >> "$GITHUB_STEP_SUMMARY"
|
|
@@ -1,22 +1,48 @@
|
|
|
1
|
-
# This file
|
|
2
|
-
#
|
|
1
|
+
# This file was autogenerated by maturin v1.13.1 and has been hand-modified
|
|
2
|
+
# to support workflow_call from release-pipeline.yaml.
|
|
3
|
+
#
|
|
4
|
+
# To regenerate, run:
|
|
3
5
|
#
|
|
4
6
|
# maturin generate-ci -o .github/workflows/publish.yaml github
|
|
5
7
|
#
|
|
8
|
+
# Regenerating will overwrite the trigger block and the per-job `if:`
|
|
9
|
+
# conditions below. Re-apply the workflow_call inputs (`dry_run`), delete
|
|
10
|
+
# the `on.workflow_run` block, remove all `if: ${{ github.event_name ... }}`
|
|
11
|
+
# guards, and wrap the `uv publish` step with the dry_run gate before
|
|
12
|
+
# committing.
|
|
6
13
|
name: Publish
|
|
7
14
|
|
|
8
15
|
on:
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
16
|
+
workflow_call:
|
|
17
|
+
inputs:
|
|
18
|
+
dry_run:
|
|
19
|
+
description: 'Build wheels but skip uv publish'
|
|
20
|
+
type: boolean
|
|
21
|
+
required: false
|
|
22
|
+
default: false
|
|
23
|
+
tag:
|
|
24
|
+
description: 'Tag to check out and build wheels from (defaults to caller ref)'
|
|
25
|
+
type: string
|
|
26
|
+
required: false
|
|
27
|
+
default: ''
|
|
12
28
|
workflow_dispatch:
|
|
29
|
+
inputs:
|
|
30
|
+
dry_run:
|
|
31
|
+
description: 'Build wheels but skip uv publish'
|
|
32
|
+
type: boolean
|
|
33
|
+
required: false
|
|
34
|
+
default: false
|
|
35
|
+
tag:
|
|
36
|
+
description: 'Tag to check out and build wheels from (defaults to current ref)'
|
|
37
|
+
type: string
|
|
38
|
+
required: false
|
|
39
|
+
default: ''
|
|
13
40
|
|
|
14
41
|
permissions:
|
|
15
42
|
contents: read
|
|
16
43
|
|
|
17
44
|
jobs:
|
|
18
45
|
linux:
|
|
19
|
-
if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }}
|
|
20
46
|
runs-on: ${{ matrix.platform.runner }}
|
|
21
47
|
strategy:
|
|
22
48
|
matrix:
|
|
@@ -35,6 +61,8 @@ jobs:
|
|
|
35
61
|
target: ppc64le
|
|
36
62
|
steps:
|
|
37
63
|
- uses: actions/checkout@v6
|
|
64
|
+
with:
|
|
65
|
+
ref: ${{ inputs.tag }}
|
|
38
66
|
- uses: actions/setup-python@v6
|
|
39
67
|
with:
|
|
40
68
|
python-version: '3.10'
|
|
@@ -59,7 +87,6 @@ jobs:
|
|
|
59
87
|
path: dist
|
|
60
88
|
|
|
61
89
|
musllinux:
|
|
62
|
-
if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }}
|
|
63
90
|
runs-on: ${{ matrix.platform.runner }}
|
|
64
91
|
strategy:
|
|
65
92
|
matrix:
|
|
@@ -74,6 +101,8 @@ jobs:
|
|
|
74
101
|
target: armv7
|
|
75
102
|
steps:
|
|
76
103
|
- uses: actions/checkout@v6
|
|
104
|
+
with:
|
|
105
|
+
ref: ${{ inputs.tag }}
|
|
77
106
|
- uses: actions/setup-python@v6
|
|
78
107
|
with:
|
|
79
108
|
python-version: '3.10'
|
|
@@ -98,7 +127,6 @@ jobs:
|
|
|
98
127
|
path: dist
|
|
99
128
|
|
|
100
129
|
windows:
|
|
101
|
-
if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }}
|
|
102
130
|
runs-on: ${{ matrix.platform.runner }}
|
|
103
131
|
strategy:
|
|
104
132
|
matrix:
|
|
@@ -114,6 +142,8 @@ jobs:
|
|
|
114
142
|
python_arch: arm64
|
|
115
143
|
steps:
|
|
116
144
|
- uses: actions/checkout@v6
|
|
145
|
+
with:
|
|
146
|
+
ref: ${{ inputs.tag }}
|
|
117
147
|
- uses: actions/setup-python@v6
|
|
118
148
|
with:
|
|
119
149
|
python-version: '3.13'
|
|
@@ -141,7 +171,6 @@ jobs:
|
|
|
141
171
|
path: dist
|
|
142
172
|
|
|
143
173
|
macos:
|
|
144
|
-
if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }}
|
|
145
174
|
runs-on: ${{ matrix.platform.runner }}
|
|
146
175
|
strategy:
|
|
147
176
|
matrix:
|
|
@@ -152,6 +181,8 @@ jobs:
|
|
|
152
181
|
target: aarch64
|
|
153
182
|
steps:
|
|
154
183
|
- uses: actions/checkout@v6
|
|
184
|
+
with:
|
|
185
|
+
ref: ${{ inputs.tag }}
|
|
155
186
|
- uses: actions/setup-python@v6
|
|
156
187
|
with:
|
|
157
188
|
python-version: '3.10'
|
|
@@ -177,10 +208,11 @@ jobs:
|
|
|
177
208
|
path: dist
|
|
178
209
|
|
|
179
210
|
sdist:
|
|
180
|
-
if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }}
|
|
181
211
|
runs-on: ubuntu-latest
|
|
182
212
|
steps:
|
|
183
213
|
- uses: actions/checkout@v6
|
|
214
|
+
with:
|
|
215
|
+
ref: ${{ inputs.tag }}
|
|
184
216
|
- name: Build sdist
|
|
185
217
|
uses: PyO3/maturin-action@v1
|
|
186
218
|
with:
|
|
@@ -196,7 +228,6 @@ jobs:
|
|
|
196
228
|
environment: pypi
|
|
197
229
|
name: Release
|
|
198
230
|
runs-on: ubuntu-latest
|
|
199
|
-
if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }}
|
|
200
231
|
needs: [linux, musllinux, windows, macos, sdist]
|
|
201
232
|
permissions:
|
|
202
233
|
# Use to sign the release artifacts
|
|
@@ -214,4 +245,14 @@ jobs:
|
|
|
214
245
|
- name: Install uv
|
|
215
246
|
uses: astral-sh/setup-uv@v7
|
|
216
247
|
- name: Publish to PyPI
|
|
248
|
+
if: inputs.dry_run == false
|
|
217
249
|
run: uv publish 'wheels-*/*'
|
|
250
|
+
|
|
251
|
+
- name: Dry-run summary (skipped uv publish)
|
|
252
|
+
if: inputs.dry_run == true
|
|
253
|
+
run: |
|
|
254
|
+
{
|
|
255
|
+
echo "## Dry-run: would have published the following wheels"
|
|
256
|
+
echo
|
|
257
|
+
ls -1 wheels-*/* | sed 's/^/- /'
|
|
258
|
+
} >> "$GITHUB_STEP_SUMMARY"
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
name: Release pipeline
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
increment:
|
|
7
|
+
description: "Force a specific bump (auto = let commitizen decide)"
|
|
8
|
+
type: choice
|
|
9
|
+
required: false
|
|
10
|
+
default: "auto"
|
|
11
|
+
options: ["auto", "PATCH", "MINOR", "MAJOR"]
|
|
12
|
+
skip_bump:
|
|
13
|
+
description: "Skip bump; release/publish/merge an existing tag instead"
|
|
14
|
+
type: boolean
|
|
15
|
+
required: false
|
|
16
|
+
default: false
|
|
17
|
+
tag:
|
|
18
|
+
description: "Existing tag to release (required when skip_bump=true)"
|
|
19
|
+
type: string
|
|
20
|
+
required: false
|
|
21
|
+
default: ""
|
|
22
|
+
dry_run:
|
|
23
|
+
description: "Run end-to-end without external side effects"
|
|
24
|
+
type: boolean
|
|
25
|
+
required: false
|
|
26
|
+
default: false
|
|
27
|
+
|
|
28
|
+
permissions:
|
|
29
|
+
contents: write
|
|
30
|
+
id-token: write
|
|
31
|
+
attestations: write
|
|
32
|
+
|
|
33
|
+
jobs:
|
|
34
|
+
resolve:
|
|
35
|
+
runs-on: ubuntu-latest
|
|
36
|
+
outputs:
|
|
37
|
+
tag: ${{ steps.out.outputs.tag }}
|
|
38
|
+
steps:
|
|
39
|
+
- uses: actions/checkout@v4
|
|
40
|
+
with:
|
|
41
|
+
fetch-depth: 0
|
|
42
|
+
- name: Validate inputs
|
|
43
|
+
id: out
|
|
44
|
+
run: |
|
|
45
|
+
if [ "${{ inputs.skip_bump }}" = "true" ]; then
|
|
46
|
+
TAG="${{ inputs.tag }}"
|
|
47
|
+
if [ -z "$TAG" ]; then
|
|
48
|
+
echo "::error::skip_bump=true requires a tag input"
|
|
49
|
+
exit 1
|
|
50
|
+
fi
|
|
51
|
+
if ! echo "$TAG" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$'; then
|
|
52
|
+
echo "::error::tag '$TAG' does not match X.Y.Z"
|
|
53
|
+
exit 1
|
|
54
|
+
fi
|
|
55
|
+
git fetch --tags --quiet
|
|
56
|
+
if ! git rev-parse --verify --quiet "refs/tags/$TAG" >/dev/null; then
|
|
57
|
+
echo "::error::tag '$TAG' does not exist on the remote"
|
|
58
|
+
exit 1
|
|
59
|
+
fi
|
|
60
|
+
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
|
|
61
|
+
else
|
|
62
|
+
echo "tag=" >> "$GITHUB_OUTPUT"
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
bump:
|
|
66
|
+
needs: resolve
|
|
67
|
+
if: inputs.skip_bump == false
|
|
68
|
+
uses: ./.github/workflows/bump.yaml
|
|
69
|
+
secrets: inherit
|
|
70
|
+
with:
|
|
71
|
+
increment: ${{ inputs.increment }}
|
|
72
|
+
dry_run: ${{ inputs.dry_run }}
|
|
73
|
+
|
|
74
|
+
release:
|
|
75
|
+
needs: [resolve, bump]
|
|
76
|
+
if: |
|
|
77
|
+
always() &&
|
|
78
|
+
needs.resolve.result == 'success' &&
|
|
79
|
+
(needs.bump.result == 'success' || needs.bump.result == 'skipped')
|
|
80
|
+
uses: ./.github/workflows/release.yaml
|
|
81
|
+
secrets: inherit
|
|
82
|
+
with:
|
|
83
|
+
tag: ${{ needs.bump.outputs.tag || needs.resolve.outputs.tag }}
|
|
84
|
+
dry_run: ${{ inputs.dry_run }}
|
|
85
|
+
|
|
86
|
+
publish:
|
|
87
|
+
needs: [resolve, bump, release]
|
|
88
|
+
if: always() && needs.release.result == 'success'
|
|
89
|
+
uses: ./.github/workflows/publish.yaml
|
|
90
|
+
secrets: inherit
|
|
91
|
+
with:
|
|
92
|
+
dry_run: ${{ inputs.dry_run }}
|
|
93
|
+
tag: ${{ needs.bump.outputs.tag || needs.resolve.outputs.tag }}
|
|
94
|
+
|
|
95
|
+
merge:
|
|
96
|
+
needs: publish
|
|
97
|
+
if: always() && needs.publish.result == 'success'
|
|
98
|
+
uses: ./.github/workflows/merge.yaml
|
|
99
|
+
secrets: inherit
|
|
100
|
+
with:
|
|
101
|
+
dry_run: ${{ inputs.dry_run }}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
name: Create release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- '[0-9]+.[0-9]+.[0-9]+'
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
inputs:
|
|
9
|
+
tag:
|
|
10
|
+
description: 'Tag to release (e.g. 0.10.0)'
|
|
11
|
+
required: true
|
|
12
|
+
workflow_call:
|
|
13
|
+
inputs:
|
|
14
|
+
tag:
|
|
15
|
+
description: 'Tag to release'
|
|
16
|
+
type: string
|
|
17
|
+
required: true
|
|
18
|
+
dry_run:
|
|
19
|
+
description: 'Build the release body but do not create a GH release'
|
|
20
|
+
type: boolean
|
|
21
|
+
required: false
|
|
22
|
+
default: false
|
|
23
|
+
|
|
24
|
+
jobs:
|
|
25
|
+
release:
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
permissions:
|
|
28
|
+
contents: write
|
|
29
|
+
steps:
|
|
30
|
+
- uses: actions/checkout@v4
|
|
31
|
+
with:
|
|
32
|
+
fetch-depth: 0
|
|
33
|
+
|
|
34
|
+
- name: Resolve tag
|
|
35
|
+
id: tag
|
|
36
|
+
run: |
|
|
37
|
+
case "${{ github.event_name }}" in
|
|
38
|
+
push) echo "tag=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT ;;
|
|
39
|
+
workflow_dispatch) echo "tag=${{ inputs.tag }}" >> $GITHUB_OUTPUT ;;
|
|
40
|
+
workflow_call) echo "tag=${{ inputs.tag }}" >> $GITHUB_OUTPUT ;;
|
|
41
|
+
esac
|
|
42
|
+
|
|
43
|
+
- name: Extract changelog section
|
|
44
|
+
run: |
|
|
45
|
+
TAG="${{ steps.tag.outputs.tag }}"
|
|
46
|
+
awk -v tag="$TAG" '
|
|
47
|
+
$0 ~ "^## " tag " " { flag=1; next }
|
|
48
|
+
flag && /^## / { exit }
|
|
49
|
+
flag { print }
|
|
50
|
+
' CHANGELOG.md > body.md
|
|
51
|
+
|
|
52
|
+
- name: Dry-run summary
|
|
53
|
+
if: github.event_name == 'workflow_call' && inputs.dry_run == true
|
|
54
|
+
run: |
|
|
55
|
+
{
|
|
56
|
+
echo "## Dry-run: release ${{ steps.tag.outputs.tag }}"
|
|
57
|
+
echo
|
|
58
|
+
echo "Would create a GitHub Release with the following body:"
|
|
59
|
+
echo
|
|
60
|
+
echo '```markdown'
|
|
61
|
+
cat body.md
|
|
62
|
+
echo '```'
|
|
63
|
+
} >> "$GITHUB_STEP_SUMMARY"
|
|
64
|
+
|
|
65
|
+
- name: Create GitHub release
|
|
66
|
+
if: ${{ !(github.event_name == 'workflow_call' && inputs.dry_run == true) }}
|
|
67
|
+
uses: softprops/action-gh-release@v3
|
|
68
|
+
with:
|
|
69
|
+
tag_name: ${{ steps.tag.outputs.tag }}
|
|
70
|
+
body_path: body.md
|
|
71
|
+
token: ${{ secrets.GH_TOKEN }}
|
|
@@ -1,3 +1,59 @@
|
|
|
1
|
+
## 0.12.0 (2026-05-29)
|
|
2
|
+
|
|
3
|
+
### Feat
|
|
4
|
+
|
|
5
|
+
- **translate**: validate OHE inputs are one-hot
|
|
6
|
+
- **translate**: add validate flag for nucleotide input checking
|
|
7
|
+
|
|
8
|
+
### Fix
|
|
9
|
+
|
|
10
|
+
- **ci**: merge runs when publish succeeded after a transitive skip
|
|
11
|
+
- **ci**: allow publish to run when bump was skipped
|
|
12
|
+
- **ci**: publish.yaml checks out the bumped tag, not the dispatch SHA
|
|
13
|
+
|
|
14
|
+
### Refactor
|
|
15
|
+
|
|
16
|
+
- **translate**: gate LUT build with predicate, drop exception control-flow
|
|
17
|
+
- **translate**: single source of truth for codon LUT index
|
|
18
|
+
|
|
19
|
+
### Perf
|
|
20
|
+
|
|
21
|
+
- **translate**: route Ragged path through codon LUT
|
|
22
|
+
- **translate**: O(1) LUT codon→AA lookup — 179× speedup on bench
|
|
23
|
+
|
|
24
|
+
## 0.11.1 (2026-05-21)
|
|
25
|
+
|
|
26
|
+
### Feat
|
|
27
|
+
|
|
28
|
+
- **ci**: add release-pipeline.yaml orchestrator
|
|
29
|
+
- add on_path flag to Vertex and path stack to ShuffleBuffers
|
|
30
|
+
- specialize k=2 path to skip LUT and codes lookup
|
|
31
|
+
- add ShuffleBuffers with sparse-reset LUT
|
|
32
|
+
- add KmerIndex trait with DirectLut and HashLut impls
|
|
33
|
+
- add kmer_encode module with rolling integer encoder
|
|
34
|
+
- ragged support for ohe, decode_ohe, tokenize, decode_tokens
|
|
35
|
+
|
|
36
|
+
### Fix
|
|
37
|
+
|
|
38
|
+
- **ci**: grant orchestrator permissions required by called workflows
|
|
39
|
+
- **ci**: make merge.yaml workflow_call-able, drop workflow_run
|
|
40
|
+
- **ci**: make publish.yaml workflow_call-able, drop workflow_run
|
|
41
|
+
- **ci**: make release.yaml workflow_call-able with dry_run
|
|
42
|
+
- **ci**: make bump.yaml workflow_call-able with increment and dry_run
|
|
43
|
+
- derive per-row seeds so batches get independent shuffles
|
|
44
|
+
- support arbitrary leading/trailing dims across public functions
|
|
45
|
+
- types
|
|
46
|
+
|
|
47
|
+
### Refactor
|
|
48
|
+
|
|
49
|
+
- pool LUT and reuse buffers via ShuffleBuffers
|
|
50
|
+
- rewrite k_shuffle1 with KmerIndex strategy + u32 Vertex
|
|
51
|
+
|
|
52
|
+
### Perf
|
|
53
|
+
|
|
54
|
+
- replace two-pass Wilson with single-pass loop-erased random walk
|
|
55
|
+
- add criterion benchmark for k_shuffle
|
|
56
|
+
|
|
1
57
|
## 0.11.0 (2026-05-07)
|
|
2
58
|
|
|
3
59
|
### Feat
|
|
@@ -72,3 +72,7 @@ Only `kshuffle.rs` is compiled. It's exposed as `seqpro._k_shuffle` (called by `
|
|
|
72
72
|
- Axis arguments (`length_axis`, `ohe_axis`) are always integers referring to the NumPy axis index; negative indexing is supported.
|
|
73
73
|
- The `transforms/` module wraps functional ops into callable objects with `__call__` for use in data pipelines.
|
|
74
74
|
- Conventional commits are enforced — use `feat:`, `fix:`, `ci:`, `bump:`, `refactor:`, `docs:`, etc. prefixes.
|
|
75
|
+
|
|
76
|
+
## Skills
|
|
77
|
+
|
|
78
|
+
This repo ships an installable skill at `skills/seqpro/SKILL.md` (skills.sh layout) describing how to use seqpro. **Any PR that adds a new public feature, changes a public signature, or makes a breaking change MUST update `skills/seqpro/SKILL.md` in the same PR.** Doc-only edits and internal refactors do not require updates unless they change conventions documented in the skill. Reviewers should reject feature/breaking PRs that don't touch the skill.
|