dot-explorer 0.1.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.
Files changed (154) hide show
  1. dot_explorer-0.1.0/.cargo/config.toml +45 -0
  2. dot_explorer-0.1.0/.github/ISSUE_TEMPLATE/bug_report.md +41 -0
  3. dot_explorer-0.1.0/.github/ISSUE_TEMPLATE/feature_request.md +19 -0
  4. dot_explorer-0.1.0/.github/dependabot.yml +35 -0
  5. dot_explorer-0.1.0/.github/pull_request_template.md +81 -0
  6. dot_explorer-0.1.0/.github/workflows/ci.yml +279 -0
  7. dot_explorer-0.1.0/.github/workflows/citation-cff.yml +45 -0
  8. dot_explorer-0.1.0/.github/workflows/codspeed.yml +75 -0
  9. dot_explorer-0.1.0/.github/workflows/docs.yml +106 -0
  10. dot_explorer-0.1.0/.github/workflows/publish.yml +254 -0
  11. dot_explorer-0.1.0/.gitignore +64 -0
  12. dot_explorer-0.1.0/.pre-commit-config.yaml +115 -0
  13. dot_explorer-0.1.0/.vscode/settings.json +11 -0
  14. dot_explorer-0.1.0/CHANGELOG.md +331 -0
  15. dot_explorer-0.1.0/CITATION.cff +30 -0
  16. dot_explorer-0.1.0/CONTRIBUTING.md +166 -0
  17. dot_explorer-0.1.0/Cargo.lock +2027 -0
  18. dot_explorer-0.1.0/Cargo.toml +77 -0
  19. dot_explorer-0.1.0/LICENSE +674 -0
  20. dot_explorer-0.1.0/PKG-INFO +314 -0
  21. dot_explorer-0.1.0/README.md +269 -0
  22. dot_explorer-0.1.0/app/README.md +259 -0
  23. dot_explorer-0.1.0/app/app.py +4197 -0
  24. dot_explorer-0.1.0/app/core/__init__.py +8 -0
  25. dot_explorer-0.1.0/app/core/align.py +355 -0
  26. dot_explorer-0.1.0/app/core/annotation_colors.py +198 -0
  27. dot_explorer-0.1.0/app/core/annotation_state.py +446 -0
  28. dot_explorer-0.1.0/app/core/cache.py +190 -0
  29. dot_explorer-0.1.0/app/core/cluster.py +291 -0
  30. dot_explorer-0.1.0/app/core/export.py +68 -0
  31. dot_explorer-0.1.0/app/core/fasta.py +211 -0
  32. dot_explorer-0.1.0/app/core/genbank.py +560 -0
  33. dot_explorer-0.1.0/app/core/panels.py +238 -0
  34. dot_explorer-0.1.0/app/core/seqs.py +441 -0
  35. dot_explorer-0.1.0/app/core/state.py +136 -0
  36. dot_explorer-0.1.0/app/core/validate.py +144 -0
  37. dot_explorer-0.1.0/app/core/wheels.py +67 -0
  38. dot_explorer-0.1.0/app/requirements.txt +16 -0
  39. dot_explorer-0.1.0/app/www/aligners.js +439 -0
  40. dot_explorer-0.1.0/app/www/app.css +914 -0
  41. dot_explorer-0.1.0/app/www/bridge.js +0 -0
  42. dot_explorer-0.1.0/app/www/cluster-table.js +56 -0
  43. dot_explorer-0.1.0/app/www/color-input.js +53 -0
  44. dot_explorer-0.1.0/app/www/feature-table.js +478 -0
  45. dot_explorer-0.1.0/app/www/font.css +11 -0
  46. dot_explorer-0.1.0/app/www/fullscreen.js +121 -0
  47. dot_explorer-0.1.0/app/www/heatmap-zoom.js +166 -0
  48. dot_explorer-0.1.0/app/www/sidebar-scroll.js +116 -0
  49. dot_explorer-0.1.0/app/www/task-status.js +51 -0
  50. dot_explorer-0.1.0/benches/bench_compare.rs +30 -0
  51. dot_explorer-0.1.0/benches/bench_index.rs +25 -0
  52. dot_explorer-0.1.0/benches/bench_kmer.rs +35 -0
  53. dot_explorer-0.1.0/benches/common/mod.rs +93 -0
  54. dot_explorer-0.1.0/docs/api/cross_index.md +114 -0
  55. dot_explorer-0.1.0/docs/api/dotplot.md +7 -0
  56. dot_explorer-0.1.0/docs/api/functions.md +56 -0
  57. dot_explorer-0.1.0/docs/api/heatmap.md +6 -0
  58. dot_explorer-0.1.0/docs/api/index.md +32 -0
  59. dot_explorer-0.1.0/docs/api/paf_io.md +44 -0
  60. dot_explorer-0.1.0/docs/api/sequence_index.md +51 -0
  61. dot_explorer-0.1.0/docs/api/similarity.md +22 -0
  62. dot_explorer-0.1.0/docs/api/style.md +46 -0
  63. dot_explorer-0.1.0/docs/api/tree.md +11 -0
  64. dot_explorer-0.1.0/docs/clustering.md +151 -0
  65. dot_explorer-0.1.0/docs/development.md +306 -0
  66. dot_explorer-0.1.0/docs/index.md +69 -0
  67. dot_explorer-0.1.0/docs/installation.md +53 -0
  68. dot_explorer-0.1.0/docs/tutorials/all_vs_all_two_indices.ipynb +436 -0
  69. dot_explorer-0.1.0/docs/tutorials/clustering.ipynb +571 -0
  70. dot_explorer-0.1.0/docs/tutorials/dotplot_tutorial.ipynb +1088 -0
  71. dot_explorer-0.1.0/docs/tutorials/minimap2_paf_tutorial.ipynb +350 -0
  72. dot_explorer-0.1.0/docs/tutorials/paf_workflow.ipynb +384 -0
  73. dot_explorer-0.1.0/docs/tutorials/quickstart.ipynb +430 -0
  74. dot_explorer-0.1.0/docs/tutorials/reorder_reorient_assembly.ipynb +489 -0
  75. dot_explorer-0.1.0/docs/tutorials/write_reordered_fasta.ipynb +270 -0
  76. dot_explorer-0.1.0/docs/webapp.md +123 -0
  77. dot_explorer-0.1.0/environment-wasm.yml +30 -0
  78. dot_explorer-0.1.0/environment.yml +16 -0
  79. dot_explorer-0.1.0/pyproject.toml +166 -0
  80. dot_explorer-0.1.0/python/benchmarks/_synth.py +116 -0
  81. dot_explorer-0.1.0/python/benchmarks/test_bench_cross.py +45 -0
  82. dot_explorer-0.1.0/python/benchmarks/test_bench_fasta.py +53 -0
  83. dot_explorer-0.1.0/python/benchmarks/test_bench_html.py +80 -0
  84. dot_explorer-0.1.0/python/benchmarks/test_bench_plot.py +60 -0
  85. dot_explorer-0.1.0/python/benchmarks/test_bench_reorder.py +81 -0
  86. dot_explorer-0.1.0/python/dot_explorer/__init__.py +99 -0
  87. dot_explorer-0.1.0/python/dot_explorer/_annotation_draw.py +337 -0
  88. dot_explorer-0.1.0/python/dot_explorer/_dot_explorer.pyi +896 -0
  89. dot_explorer-0.1.0/python/dot_explorer/_html/__init__.py +13 -0
  90. dot_explorer-0.1.0/python/dot_explorer/_html/render.py +132 -0
  91. dot_explorer-0.1.0/python/dot_explorer/_html/report.css +265 -0
  92. dot_explorer-0.1.0/python/dot_explorer/_html/report.js +1731 -0
  93. dot_explorer-0.1.0/python/dot_explorer/_html/serialize.py +287 -0
  94. dot_explorer-0.1.0/python/dot_explorer/_html/template.html +46 -0
  95. dot_explorer-0.1.0/python/dot_explorer/_version.py +7 -0
  96. dot_explorer-0.1.0/python/dot_explorer/alignment_view.py +155 -0
  97. dot_explorer-0.1.0/python/dot_explorer/annotation.py +627 -0
  98. dot_explorer-0.1.0/python/dot_explorer/dotplot.py +2946 -0
  99. dot_explorer-0.1.0/python/dot_explorer/heatmap.py +299 -0
  100. dot_explorer-0.1.0/python/dot_explorer/paf_io.py +2344 -0
  101. dot_explorer-0.1.0/python/dot_explorer/similarity.py +547 -0
  102. dot_explorer-0.1.0/python/dot_explorer/style.py +129 -0
  103. dot_explorer-0.1.0/python/dot_explorer/tree.py +598 -0
  104. dot_explorer-0.1.0/scripts/add_loading_splash.py +151 -0
  105. dot_explorer-0.1.0/scripts/mem_profile_index.py +151 -0
  106. dot_explorer-0.1.0/scripts/notebooks_to_md.py +91 -0
  107. dot_explorer-0.1.0/scripts/setup_wasm_toolchain.sh +89 -0
  108. dot_explorer-0.1.0/scripts/stamp_version.py +295 -0
  109. dot_explorer-0.1.0/scripts/wasm_smoke_test.mjs +48 -0
  110. dot_explorer-0.1.0/src/error.rs +37 -0
  111. dot_explorer-0.1.0/src/fasta.rs +118 -0
  112. dot_explorer-0.1.0/src/index.rs +1289 -0
  113. dot_explorer-0.1.0/src/kmer.rs +291 -0
  114. dot_explorer-0.1.0/src/kmer_hash.rs +733 -0
  115. dot_explorer-0.1.0/src/lib.rs +65 -0
  116. dot_explorer-0.1.0/src/main.rs +3 -0
  117. dot_explorer-0.1.0/src/merge.rs +825 -0
  118. dot_explorer-0.1.0/src/paf.rs +109 -0
  119. dot_explorer-0.1.0/src/serialize.rs +163 -0
  120. dot_explorer-0.1.0/src/strand.rs +89 -0
  121. dot_explorer-0.1.0/tests/__init__.py +0 -0
  122. dot_explorer-0.1.0/tests/conftest.py +29 -0
  123. dot_explorer-0.1.0/tests/data/.gitkeep +0 -0
  124. dot_explorer-0.1.0/tests/data/example.treefile +1 -0
  125. dot_explorer-0.1.0/tests/data/sample.gbk +68 -0
  126. dot_explorer-0.1.0/tests/test_alignment_view.py +90 -0
  127. dot_explorer-0.1.0/tests/test_annotation.py +558 -0
  128. dot_explorer-0.1.0/tests/test_annotation_draw.py +707 -0
  129. dot_explorer-0.1.0/tests/test_app_align.py +421 -0
  130. dot_explorer-0.1.0/tests/test_app_cluster.py +219 -0
  131. dot_explorer-0.1.0/tests/test_app_core.py +1254 -0
  132. dot_explorer-0.1.0/tests/test_app_genbank.py +265 -0
  133. dot_explorer-0.1.0/tests/test_app_seqs.py +125 -0
  134. dot_explorer-0.1.0/tests/test_app_state.py +444 -0
  135. dot_explorer-0.1.0/tests/test_data.py +14 -0
  136. dot_explorer-0.1.0/tests/test_dotplot.py +2340 -0
  137. dot_explorer-0.1.0/tests/test_fasta.py +36 -0
  138. dot_explorer-0.1.0/tests/test_gravity_parity.py +96 -0
  139. dot_explorer-0.1.0/tests/test_heatmap.py +213 -0
  140. dot_explorer-0.1.0/tests/test_html_report.py +643 -0
  141. dot_explorer-0.1.0/tests/test_index.py +420 -0
  142. dot_explorer-0.1.0/tests/test_kmer.py +68 -0
  143. dot_explorer-0.1.0/tests/test_kmer_index_parity.py +138 -0
  144. dot_explorer-0.1.0/tests/test_merge.py +427 -0
  145. dot_explorer-0.1.0/tests/test_paf.py +44 -0
  146. dot_explorer-0.1.0/tests/test_paf_io.py +1332 -0
  147. dot_explorer-0.1.0/tests/test_private_data.py +86 -0
  148. dot_explorer-0.1.0/tests/test_serialize.py +29 -0
  149. dot_explorer-0.1.0/tests/test_similarity.py +248 -0
  150. dot_explorer-0.1.0/tests/test_strand.py +327 -0
  151. dot_explorer-0.1.0/tests/test_style.py +130 -0
  152. dot_explorer-0.1.0/tests/test_tree.py +187 -0
  153. dot_explorer-0.1.0/tests/test_version.py +75 -0
  154. dot_explorer-0.1.0/zensical.toml +117 -0
@@ -0,0 +1,45 @@
1
+ # Flags for building the Pyodide (browser) wheel. The target Pyodide release
2
+ # is 0.27.x (bundled by current Shinylive): CPython 3.12 + Emscripten 3.1.58,
3
+ # so builds MUST use emsdk 3.1.58 exactly — a mismatched emcc version produces
4
+ # a wheel whose platform tag micropip rejects at load time.
5
+ #
6
+ # SIDE_MODULE=2 build a dynamic library loadable by Pyodide's main
7
+ # module (=1 chokes on Rust's lib.rmeta)
8
+ # WASM_BIGINT i64 <-> BigInt at the JS boundary
9
+ # relocation-model=pic required for side modules (else R_WASM_TABLE_INDEX
10
+ # link errors)
11
+ # link-native-libraries=no stop rustc passing nonexistent emscripten C libs
12
+ # to the linker (nightly-only -Z flag, so wasm builds
13
+ # need a nightly toolchain). Use the pinned
14
+ # RUSTUP_TOOLCHAIN=nightly-2025-05-01: newer nightlies
15
+ # default to wasm-exceptions (incompatible with
16
+ # Pyodide 0.27's non-EH ABI); older ones predate
17
+ # stdlib APIs used by bio 4.x.
18
+ #
19
+ # The earlier opt-level=0 workaround (emsdk 3.1.65's wasm-opt not knowing
20
+ # --enable-bulk-memory-opt) is no longer needed on 3.1.58.
21
+ [target.wasm32-unknown-emscripten]
22
+ rustflags = [
23
+ "-C", "link-arg=-sSIDE_MODULE=2",
24
+ "-C", "link-arg=-sWASM_BIGINT",
25
+ "-C", "relocation-model=pic",
26
+ "-Z", "link-native-libraries=no",
27
+ # Appended after rustc's own "-O3", so emcc links at -O0 and skips its
28
+ # wasm-opt post-processing pass entirely (modern LLVM emits the
29
+ # bulk-memory-opt feature, which emsdk 3.1.58's bundled wasm-opt rejects
30
+ # with "Unknown option '--enable-bulk-memory-opt'"). The Rust code itself
31
+ # is still compiled at opt-level 3 — only the binaryen pass is skipped.
32
+ "-C", "link-arg=-O0",
33
+ ]
34
+
35
+ # On macOS, the pyo3 `extension-module` cdylib leaves Python symbols undefined
36
+ # to be resolved by the host interpreter at load time. Standalone `cargo`
37
+ # invocations (`test`, `bench`, `build`) that link that cdylib need the linker
38
+ # told to allow those undefined symbols, or the link fails. These entries are
39
+ # target-scoped to macOS and do not affect Linux CI, wasm, or the maturin wheel
40
+ # build (which sets its own linker args).
41
+ [target.x86_64-apple-darwin]
42
+ rustflags = ["-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup"]
43
+
44
+ [target.aarch64-apple-darwin]
45
+ rustflags = ["-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup"]
@@ -0,0 +1,41 @@
1
+ ---
2
+ name: Bug report
3
+ about: Create a report to help us improve
4
+ title: ""
5
+ labels: ""
6
+ assignees: ""
7
+ ---
8
+
9
+ **Describe the bug**
10
+ A clear and concise description of what the bug is.
11
+
12
+ **To Reproduce**
13
+ Steps to reproduce the behavior:
14
+
15
+ 1. When I run this command `...`
16
+ 2. With these input files: [Attach sample minimal input files if applicable]
17
+ 3. I get the following error:
18
+
19
+ ```code
20
+ YOUR ERROR MESSAGE HERE
21
+ ```
22
+
23
+ **Expected behavior**
24
+ A clear and concise description of what you expected to happen.
25
+
26
+ **Screenshots**
27
+ If applicable, add screenshots to help explain your problem.
28
+
29
+ **Environment (please complete the following information):**
30
+
31
+ - Python version: [output of `python --version`]
32
+ - Platform: [output of `uname -a` or `systeminfo`]
33
+
34
+ **System information**
35
+
36
+ - OS: [e.g. MacOS, Windows, Ubuntu]
37
+ - Version [e.g. Sequoia 15.1.1, Windows 10, Ubuntu 20.04]
38
+ - Processor: [e.g. Intel i7, AMD Ryzen 5]
39
+
40
+ **Additional context**
41
+ Add any other context about the problem here.
@@ -0,0 +1,19 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest an idea for this project
4
+ title: ""
5
+ labels: ""
6
+ assignees: ""
7
+ ---
8
+
9
+ **Is your feature request related to a problem? Please describe.**
10
+ A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
11
+
12
+ **Describe the solution you'd like**
13
+ A clear and concise description of what you want to happen.
14
+
15
+ **Describe alternatives you've considered**
16
+ A clear and concise description of any alternative solutions or features you've considered.
17
+
18
+ **Additional context**
19
+ Add any other context or screenshots about the feature request here.
@@ -0,0 +1,35 @@
1
+ # To get started with Dependabot version updates, you'll need to specify which
2
+ # package ecosystems to update and where the package manifests are located.
3
+ # Please see the documentation for all configuration options:
4
+ # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
5
+
6
+ version: 2
7
+ updates:
8
+ - package-ecosystem: "cargo"
9
+ directory: "/"
10
+ schedule:
11
+ interval: "monthly"
12
+ groups:
13
+ monthly-batch:
14
+ patterns:
15
+ - "*"
16
+ - package-ecosystem: "github-actions"
17
+ directory: "/"
18
+ schedule:
19
+ interval: "monthly"
20
+ groups:
21
+ monthly-batch:
22
+ patterns:
23
+ - "*"
24
+ - package-ecosystem: "pre-commit"
25
+ directory: "/"
26
+ schedule:
27
+ interval: "monthly" # Choose daily, weekly, or monthly
28
+ groups:
29
+ monthly-batch:
30
+ patterns:
31
+ - "*"
32
+ # - package-ecosystem: "pip"
33
+ # directory: "/" # Location of pyproject.toml for Python dependencies
34
+ # schedule:
35
+ # interval: "weekly"
@@ -0,0 +1,81 @@
1
+ ## What and why
2
+
3
+ <!-- What does this change, and what problem does it solve? Link any issue:
4
+ "Fixes #123" / "Part of #123". -->
5
+
6
+ ## Type of change
7
+
8
+ <!-- Tick all that apply. The PR title is squash-merged as the commit message,
9
+ so please make it a Conventional Commit line, e.g.
10
+ `feat(app): colour alignments by identity` or `fix(plot): ...`.
11
+ Use `!` (`refactor!:`) for a breaking change. -->
12
+
13
+ - [ ] Bug fix
14
+ - [ ] New feature
15
+ - [ ] Performance
16
+ - [ ] Documentation
17
+ - [ ] Build / CI / dependencies
18
+ - [ ] Breaking change (API, CLI, or output format)
19
+
20
+ ## How was this tested?
21
+
22
+ <!-- New/updated tests, and anything you checked by hand (e.g. rendered a plot,
23
+ ran the app, opened an HTML report). -->
24
+
25
+ ## Checklist
26
+
27
+ - [ ] `cargo fmt --all -- --check`, `cargo clippy -- -D warnings` and `cargo test` pass
28
+ - [ ] `ruff format`/`ruff check` clean and `pytest tests/ -v` passes
29
+ - [ ] Tests added or updated for the change
30
+ - [ ] `CHANGELOG.md` updated under `## [Unreleased]`
31
+ - [ ] Docs updated (`docs/`, module docstrings, or `app/README.md`) if behaviour changed
32
+
33
+ ## Project-specific checks
34
+
35
+ <!-- Delete the sections that do not apply to this PR. -->
36
+
37
+ **Touched `src/*.rs`**
38
+
39
+ - [ ] Rebuilt with `maturin develop` and re-ran the Python suite
40
+ - [ ] New `needletail` / `rayon` use is `#[cfg(feature = ...)]`-gated, and Python
41
+ callers degrade gracefully without it (the wasm build uses
42
+ `--no-default-features`)
43
+ - [ ] `python/dot_explorer/_dot_explorer.pyi` stubs updated to match any changed
44
+ signature
45
+ - [ ] Nothing added that holds GIL-bound cross-call state (statics,
46
+ `GILOnceCell`, `thread_local`, `unsendable` pyclasses) — the module is
47
+ declared `gil_used = false`
48
+
49
+ **Touched the matching or contig-ordering path**
50
+
51
+ - [ ] `tests/test_kmer_index_parity.py` still passes unchanged
52
+ - [ ] Gravity ordering changed in *both* engines (Rust
53
+ `SequenceIndex.optimal_contig_order` and Python
54
+ `paf_io.compute_gravity_contigs`), with
55
+ `tests/test_gravity_parity.py` passing
56
+
57
+ **Performance-sensitive change**
58
+
59
+ - [ ] Benchmark numbers included below (`cargo bench`, `pytest python/benchmarks
60
+ --codspeed`, and/or `python scripts/mem_profile_index.py`) — memory counts
61
+ as much as speed, since the browser app runs in a ~4 GB wasm heap
62
+
63
+ **Touched `app/`**
64
+
65
+ - [ ] Logic went in `app/core/` (with tests in `tests/test_app_*.py`), not
66
+ `app/app.py`
67
+ - [ ] Verified natively (`shiny run app/app.py`)
68
+ - [ ] Verified in a Shinylive export, if the change could behave differently
69
+ under Pyodide (no threads, no native FASTA reader, sourmash 4.8 APIs only)
70
+ - [ ] Pinned wasm toolchain versions unchanged, or the change is explained in
71
+ the PR body (see `app/README.md`)
72
+
73
+ **Touched clustering / similarity**
74
+
75
+ - [ ] Restricted to sourmash 4.8-era APIs (Pyodide bundles 4.8.11)
76
+ - [ ] Optional imports still `importorskip`-ed so the suite runs without the
77
+ `cluster` extra
78
+
79
+ **Touched `docs/tutorials/`**
80
+
81
+ - [ ] Edited the `.ipynb` notebooks, not the generated `.md` build products
@@ -0,0 +1,279 @@
1
+ name: CI
2
+
3
+ on:
4
+ # Trigger on push to main (post-merge) and on all pull requests to main.
5
+ # Omitting push to feature branches avoids duplicate runs when a PR is open.
6
+ push:
7
+ branches: ["main"]
8
+ pull_request:
9
+ branches: ["main"]
10
+
11
+ jobs:
12
+ rust-tests:
13
+ name: Rust Tests
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v7
17
+ - name: Install Rust stable
18
+ uses: dtolnay/rust-toolchain@stable
19
+ - name: Add clippy and rustfmt components
20
+ run: |
21
+ rustup component add clippy
22
+ rustup component add rustfmt
23
+ - name: Cache cargo registry
24
+ uses: actions/cache@v6
25
+ with:
26
+ path: |
27
+ ~/.cargo/registry
28
+ ~/.cargo/git
29
+ target
30
+ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
31
+ - name: Check formatting
32
+ run: cargo fmt -- --check
33
+ - name: Run clippy
34
+ run: cargo clippy -- -D warnings
35
+ - name: Run cargo tests
36
+ run: cargo test
37
+ - name: Run cargo check
38
+ run: cargo check
39
+
40
+ version-check:
41
+ name: Version Stamp Check
42
+ runs-on: ubuntu-latest
43
+ steps:
44
+ - uses: actions/checkout@v7
45
+ with:
46
+ # Full history + tags: scripts/stamp_version.py derives the
47
+ # version from `git describe`.
48
+ fetch-depth: 0
49
+ fetch-tags: true
50
+ - name: Check stamped versions match the latest tag
51
+ run: python scripts/stamp_version.py --check
52
+
53
+ python-lint:
54
+ name: Python Lint and Format
55
+ if: ${{ github.actor != 'dependabot[bot]' }}
56
+ runs-on: ubuntu-latest
57
+ permissions:
58
+ contents: write
59
+ pull-requests: write
60
+ steps:
61
+ - uses: actions/checkout@v7
62
+ with:
63
+ ref: ${{ github.sha }}
64
+ token: ${{ secrets.GITHUB_TOKEN }}
65
+ - uses: astral-sh/ruff-action@v3
66
+ with:
67
+ src: "./python ./tests"
68
+ args: "format"
69
+ - uses: astral-sh/ruff-action@v3
70
+ with:
71
+ src: "./python ./tests"
72
+ args: "check --fix"
73
+ - uses: isort/isort-action@v1
74
+ with:
75
+ configuration: "--settings-path=./pyproject.toml"
76
+ paths: "./python ./tests"
77
+ - uses: stefanzweifel/git-auto-commit-action@v7
78
+ id: auto-commit-action
79
+ with:
80
+ commit_message: "Style fixes by Ruff"
81
+
82
+ python-tests:
83
+ name: Python Tests
84
+ runs-on: ubuntu-latest
85
+ needs: rust-tests
86
+ steps:
87
+ - uses: actions/checkout@v7
88
+ - name: Set up Python
89
+ uses: actions/setup-python@v7
90
+ with:
91
+ python-version: "3.14"
92
+ - name: Install Rust stable
93
+ uses: dtolnay/rust-toolchain@stable
94
+ - name: Cache cargo registry
95
+ uses: actions/cache@v6
96
+ with:
97
+ path: |
98
+ ~/.cargo/registry
99
+ ~/.cargo/git
100
+ target
101
+ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
102
+ - name: Install maturin and dependencies
103
+ # sourmash + scipy cover the `cluster` extra (tests/test_similarity.py
104
+ # and friends importorskip them, so a failed install only skips).
105
+ run: |
106
+ pip install maturin pytest pytest-cov matplotlib numpy shiny pyfaidx sourmash scipy
107
+ - name: Build and install dot-explorer
108
+ run: |
109
+ maturin build --release
110
+ pip install target/wheels/*.whl
111
+ - name: Run pytest
112
+ run: pytest tests/ -v
113
+
114
+ python-tests-freethreaded:
115
+ name: Python Tests (free-threaded 3.14t)
116
+ runs-on: ubuntu-latest
117
+ needs: rust-tests
118
+ env:
119
+ # Refuse to let the interpreter quietly turn the GIL back on, and warn on
120
+ # any extension that has not opted into free-threading.
121
+ PYTHON_GIL: "0"
122
+ PYTHONWARNDEFAULTTHREADSAFETY: "1"
123
+ steps:
124
+ - uses: actions/checkout@v7
125
+ - name: Set up free-threaded Python
126
+ uses: actions/setup-python@v7
127
+ with:
128
+ python-version: "3.14t"
129
+ - name: Install Rust stable
130
+ uses: dtolnay/rust-toolchain@stable
131
+ - name: Cache cargo registry
132
+ uses: actions/cache@v6
133
+ with:
134
+ path: |
135
+ ~/.cargo/registry
136
+ ~/.cargo/git
137
+ target
138
+ key: ${{ runner.os }}-cargo-ft-${{ hashFiles('**/Cargo.lock') }}
139
+ - name: Install maturin and dependencies
140
+ # No shiny here, unlike the GIL build: it pulls orjson, which has no
141
+ # free-threaded wheel and fails to build from source. The suite does
142
+ # not need it (same 741 passed / 6 skipped either way). pyfaidx is
143
+ # pure Python, so it is safe on 3.14t (tests/test_app_seqs.py).
144
+ # sourmash ships abi-agnostic (py2.py3, CFFI) wheels and scipy has
145
+ # cp314t wheels, so the cluster extra runs here too; the similarity
146
+ # tests importorskip them if either install ever breaks.
147
+ run: |
148
+ pip install maturin pytest pytest-cov matplotlib numpy pyfaidx sourmash scipy
149
+ - name: Clean wheels directory
150
+ run: rm -rf target/wheels/
151
+ - name: Build and install dot-explorer
152
+ # The wheel is tagged cp314-cp314t (python tag cp314, abi tag cp314t).
153
+ run: |
154
+ maturin build --release
155
+ pip install target/wheels/*cp314t*.whl
156
+ - name: Assert the extension does not re-enable the GIL
157
+ # src/lib.rs declares #[pymodule(gil_used = false)]. If that is ever
158
+ # dropped, importing the module flips the GIL back on and the cp314t
159
+ # wheel we publish is free-threaded in name only -- fail here instead.
160
+ run: |
161
+ python -c "import sys, dot_explorer; assert not sys._is_gil_enabled(), 'GIL re-enabled on import'"
162
+ - name: Run pytest
163
+ run: pytest tests/ -v
164
+
165
+ native-wheel-build:
166
+ name: Native Wheel Build
167
+ runs-on: ubuntu-latest
168
+ needs: rust-tests
169
+ steps:
170
+ - uses: actions/checkout@v7
171
+ - name: Install Rust stable
172
+ uses: dtolnay/rust-toolchain@stable
173
+ - name: Set up Python
174
+ uses: actions/setup-python@v7
175
+ with:
176
+ python-version: "3.14"
177
+ - name: Cache cargo registry
178
+ uses: actions/cache@v6
179
+ with:
180
+ path: |
181
+ ~/.cargo/registry
182
+ ~/.cargo/git
183
+ target
184
+ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
185
+ - name: Install maturin
186
+ run: pip install maturin
187
+ - name: Build native wheel
188
+ run: maturin build --release
189
+ - name: Upload native wheel artifact
190
+ uses: actions/upload-artifact@v7
191
+ with:
192
+ name: native-wheel
193
+ path: target/wheels/*.whl
194
+
195
+ wasm-build:
196
+ name: Wasm (Pyodide) Wheel Build
197
+ runs-on: ubuntu-latest
198
+ # Run independently; a wasm build failure does not block other jobs.
199
+ continue-on-error: true
200
+ steps:
201
+ - uses: actions/checkout@v7
202
+ - name: Install Rust nightly with wasm32-unknown-emscripten target
203
+ # Nightly is required by the -Z link-native-libraries=no flag in
204
+ # .cargo/config.toml. Pinned to nightly-2025-05-01: newer nightlies
205
+ # emit wasm-exceptions by default (incompatible with Pyodide 0.27's
206
+ # non-EH ABI), while older ones predate stdlib APIs our deps use
207
+ # (bio 4.x needs is_multiple_of, stabilised in Rust 1.87).
208
+ uses: dtolnay/rust-toolchain@master
209
+ with:
210
+ toolchain: nightly-2025-05-01
211
+ targets: wasm32-unknown-emscripten
212
+ - name: Set up Emscripten SDK
213
+ uses: mymindstorm/setup-emsdk@v16
214
+ with:
215
+ # MUST match the Emscripten version of the target Pyodide release.
216
+ # Pyodide 0.27.x (bundled by current Shinylive) = emsdk 3.1.58.
217
+ # The wheel platform tag derives from this version and micropip
218
+ # rejects mismatches.
219
+ version: 3.1.58
220
+ - name: Set up Python
221
+ uses: actions/setup-python@v7
222
+ with:
223
+ # Pinned to 3.12: Pyodide 0.27 ships CPython 3.12.7, so the wasm
224
+ # wheel must be built against a matching interpreter version.
225
+ python-version: "3.12"
226
+ - name: Cache cargo registry
227
+ uses: actions/cache@v6
228
+ with:
229
+ path: |
230
+ ~/.cargo/registry
231
+ ~/.cargo/git
232
+ target
233
+ key: ${{ runner.os }}-wasm-cargo-${{ hashFiles('**/Cargo.lock') }}
234
+ - name: Install maturin
235
+ run: pip install maturin
236
+ - name: Build wasm wheel
237
+ # rm: the cargo cache restores target/wheels from earlier runs
238
+ # (other Emscripten versions); stale wheels must not reach the
239
+ # artifact (one previously shipped inside the deployed app).
240
+ run: >
241
+ rm -rf target/wheels &&
242
+ maturin build --release
243
+ --target wasm32-unknown-emscripten
244
+ --no-default-features
245
+ -i python3.12
246
+ - name: Check wheel platform tag
247
+ run: |
248
+ ls target/wheels/
249
+ ls target/wheels/*cp312-cp312-emscripten_3_1_58_wasm32.whl
250
+ - name: Smoke-test wheel under Pyodide (Node)
251
+ run: |
252
+ npm install pyodide@0.27.7
253
+ node scripts/wasm_smoke_test.mjs target/wheels/*cp312*emscripten*.whl
254
+ - name: Upload wasm wheel artifact
255
+ uses: actions/upload-artifact@v7
256
+ with:
257
+ name: wasm-wheel
258
+ path: target/wheels/*cp312-cp312-emscripten_3_1_58_wasm32.whl
259
+
260
+ docs-build:
261
+ name: Docs Build
262
+ runs-on: ubuntu-latest
263
+ steps:
264
+ - uses: actions/checkout@v7
265
+ - name: Install Rust stable
266
+ uses: dtolnay/rust-toolchain@stable
267
+ - name: Set up Python
268
+ uses: actions/setup-python@v7
269
+ with:
270
+ python-version: "3.12"
271
+ - name: Install docs dependencies
272
+ # Builds the compiled extension too: mkdocstrings imports dot_explorer
273
+ # to document it.
274
+ run: pip install ".[docs]"
275
+ - name: Render tutorial notebooks to Markdown
276
+ run: python scripts/notebooks_to_md.py
277
+ - name: Build docs site
278
+ # Same command as the deploy workflow, minus the app export.
279
+ run: zensical build --clean --strict
@@ -0,0 +1,45 @@
1
+ name: Citation CFF
2
+
3
+ on:
4
+ push:
5
+ paths:
6
+ - CITATION.cff
7
+ tags:
8
+ # Match semantic version tags: v1.0.0, v1.2.3, v2.0.0-beta, etc.
9
+ # Excludes moving tags: v1, v2
10
+ - "v[0-9]+.[0-9]+.[0-9]+*"
11
+ workflow_dispatch:
12
+
13
+ permissions:
14
+ contents: write
15
+ pull-requests: write
16
+
17
+ jobs:
18
+ validate:
19
+ name: Validate CITATION.cff
20
+ runs-on: ubuntu-latest
21
+ steps:
22
+ - name: Checkout
23
+ uses: actions/checkout@v7
24
+ - name: Validate CITATION.cff
25
+ uses: dieghernan/cff-validator@v5
26
+ env:
27
+ GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
28
+
29
+ update:
30
+ name: Update CITATION.cff
31
+ runs-on: ubuntu-latest
32
+ needs: validate
33
+ if: startsWith(github.ref, 'refs/tags/v')
34
+ steps:
35
+ - name: Checkout
36
+ uses: actions/checkout@v7
37
+ with:
38
+ fetch-depth: 0
39
+ - name: Sync version and date in CITATION.cff
40
+ uses: Adamtaranto/citation-sync-action@v1
41
+ with:
42
+ token: ${{ secrets.GITHUB_TOKEN }}
43
+ # Create PR instead of pushing to main
44
+ use-pull-request: true
45
+ update-mode: "match"
@@ -0,0 +1,75 @@
1
+ name: CodSpeed
2
+ on:
3
+ # push:
4
+ # branches: [main]
5
+ pull_request:
6
+ branches: [main]
7
+ paths:
8
+ - "benches/**"
9
+ - "src/**"
10
+ - "python/**"
11
+ - ".github/workflows/codspeed.yml"
12
+ # `workflow_dispatch` allows CodSpeed to trigger backtest
13
+ # performance analysis in order to generate initial data.
14
+ workflow_dispatch:
15
+ concurrency:
16
+ group: codspeed-${{ github.workflow }}-${{ github.ref }}
17
+ cancel-in-progress: true
18
+ permissions:
19
+ contents: read
20
+ id-token: write # for OpenID Connect authentication with CodSpeed
21
+ jobs:
22
+ rust-benchmarks:
23
+ if: ${{ github.actor != 'dependabot[bot]' }} # Do not run on commits created by dependabot
24
+ name: Rust benchmarks
25
+ runs-on: ubuntu-latest
26
+ steps:
27
+ - uses: actions/checkout@v7
28
+ - uses: actions/setup-python@v7
29
+ with:
30
+ python-version: '3.14'
31
+ # The bench binary links `_dot_explorer` (an rlib), which pulls in pyo3 built
32
+ # without the `extension-module` feature, so it dynamically links
33
+ # libpython. Pin the interpreter for the build and expose its lib dir so
34
+ # the loader can find libpython when `cargo codspeed run` executes the
35
+ # bench binary. Without this the run relies on the runner's default
36
+ # library path, which is not guaranteed.
37
+ - name: Expose libpython for the pyo3-linked bench binary
38
+ run: |
39
+ echo "PYO3_PYTHON=$(which python)" >> "$GITHUB_ENV"
40
+ echo "LD_LIBRARY_PATH=$(python -c 'import sysconfig; print(sysconfig.get_config_var("LIBDIR"))')${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" >> "$GITHUB_ENV"
41
+ - name: Setup rust toolchain, cache and cargo-codspeed binary
42
+ uses: moonrepo/setup-rust@v1
43
+ with:
44
+ channel: stable
45
+ cache-target: release
46
+ bins: cargo-codspeed
47
+ - name: Build the benchmark target(s)
48
+ run: cargo codspeed build
49
+ - name: Run the benchmarks
50
+ uses: CodSpeedHQ/action@v5
51
+ with:
52
+ mode: simulation
53
+ run: cargo codspeed run
54
+ python-benchmarks:
55
+ if: ${{ github.actor != 'dependabot[bot]' }} # Do not run on commits created by dependabot
56
+ name: Python benchmarks
57
+ runs-on: ubuntu-latest
58
+ steps:
59
+ - uses: actions/checkout@v7
60
+ - uses: actions/setup-python@v7
61
+ with:
62
+ python-version: '3.14'
63
+ # maturin needs cargo to build the extension from the sdist/source tree.
64
+ - uses: dtolnay/rust-toolchain@stable
65
+ - name: Build dot-explorer and install benchmark dependencies
66
+ # The maturin build backend compiles the extension; .[test] also pulls
67
+ # in pytest and pytest-codspeed.
68
+ run: |
69
+ python -m pip install --upgrade pip
70
+ pip install '.[test]'
71
+ - name: Run the benchmarks
72
+ uses: CodSpeedHQ/action@v5
73
+ with:
74
+ mode: simulation
75
+ run: pytest python/benchmarks --codspeed