gseek 0.2.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.
- gseek-0.2.0/.editorconfig +18 -0
- gseek-0.2.0/.gitignore +58 -0
- gseek-0.2.0/.pre-commit-config.yaml +35 -0
- gseek-0.2.0/.python-version +1 -0
- gseek-0.2.0/AGENTS.md +198 -0
- gseek-0.2.0/CHANGELOG.md +151 -0
- gseek-0.2.0/CONTRIBUTING.md +126 -0
- gseek-0.2.0/LICENSE +21 -0
- gseek-0.2.0/PKG-INFO +252 -0
- gseek-0.2.0/README.md +216 -0
- gseek-0.2.0/dev/adapter-matrix.md +627 -0
- gseek-0.2.0/dev/compatibility.md +321 -0
- gseek-0.2.0/dev/decisions/0001-mummer4.md +79 -0
- gseek-0.2.0/dev/decisions/0002-project-rename.md +70 -0
- gseek-0.2.0/dev/decisions/README.md +15 -0
- gseek-0.2.0/dev/development-plan.md +1072 -0
- gseek-0.2.0/dev/releasing.md +143 -0
- gseek-0.2.0/dev/research.md +253 -0
- gseek-0.2.0/docs/api.md +1631 -0
- gseek-0.2.0/docs/cli.md +113 -0
- gseek-0.2.0/docs/errors.md +99 -0
- gseek-0.2.0/docs/index.md +23 -0
- gseek-0.2.0/docs/quickstart.md +146 -0
- gseek-0.2.0/pyproject.toml +137 -0
- gseek-0.2.0/src/gseek/__init__.py +198 -0
- gseek-0.2.0/src/gseek/__main__.py +8 -0
- gseek-0.2.0/src/gseek/adapter.py +292 -0
- gseek-0.2.0/src/gseek/adapters/__init__.py +17 -0
- gseek-0.2.0/src/gseek/adapters/base.py +214 -0
- gseek-0.2.0/src/gseek/adapters/blast.py +395 -0
- gseek-0.2.0/src/gseek/adapters/bwa.py +396 -0
- gseek-0.2.0/src/gseek/adapters/kma.py +284 -0
- gseek-0.2.0/src/gseek/adapters/mash.py +326 -0
- gseek-0.2.0/src/gseek/adapters/minimap2.py +346 -0
- gseek-0.2.0/src/gseek/adapters/mummer.py +241 -0
- gseek-0.2.0/src/gseek/adapters/skani.py +243 -0
- gseek-0.2.0/src/gseek/adapters/sourmash.py +446 -0
- gseek-0.2.0/src/gseek/api.py +261 -0
- gseek-0.2.0/src/gseek/capabilities.py +132 -0
- gseek-0.2.0/src/gseek/cli.py +345 -0
- gseek-0.2.0/src/gseek/errors.py +245 -0
- gseek-0.2.0/src/gseek/execution.py +792 -0
- gseek-0.2.0/src/gseek/index.py +443 -0
- gseek-0.2.0/src/gseek/io.py +427 -0
- gseek-0.2.0/src/gseek/model/__init__.py +32 -0
- gseek-0.2.0/src/gseek/model/alignment.py +612 -0
- gseek-0.2.0/src/gseek/model/common.py +148 -0
- gseek-0.2.0/src/gseek/model/distance.py +202 -0
- gseek-0.2.0/src/gseek/model/run.py +220 -0
- gseek-0.2.0/src/gseek/provenance.py +373 -0
- gseek-0.2.0/src/gseek/py.typed +0 -0
- gseek-0.2.0/src/gseek/registry.py +206 -0
- gseek-0.2.0/src/gseek/replay.py +161 -0
- gseek-0.2.0/src/gseek/runner.py +627 -0
- gseek-0.2.0/src/gseek/types.py +205 -0
- gseek-0.2.0/src/gseek/version.py +7 -0
- gseek-0.2.0/src/gseek/views.py +129 -0
- gseek-0.2.0/tests/conftest.py +219 -0
- gseek-0.2.0/tests/fixtures/README.md +80 -0
- gseek-0.2.0/tests/fixtures/blast/blastn_nucl.tsv +2 -0
- gseek-0.2.0/tests/fixtures/bwa/align.sam +6 -0
- gseek-0.2.0/tests/fixtures/kma/align.res +3 -0
- gseek-0.2.0/tests/fixtures/mash/dist.tsv +2 -0
- gseek-0.2.0/tests/fixtures/mash/screen.tsv +2 -0
- gseek-0.2.0/tests/fixtures/minimap2/align.paf +2 -0
- gseek-0.2.0/tests/fixtures/mummer/coords.txt +6 -0
- gseek-0.2.0/tests/fixtures/skani/search.tsv +2 -0
- gseek-0.2.0/tests/fixtures/sourmash/gather.csv +3 -0
- gseek-0.2.0/tests/fixtures/sourmash/search.csv +3 -0
- gseek-0.2.0/tests/integration/__init__.py +0 -0
- gseek-0.2.0/tests/integration/test_external_reference.py +98 -0
- gseek-0.2.0/tests/integration/test_m1_adapters.py +134 -0
- gseek-0.2.0/tests/integration/test_m2_adapters.py +128 -0
- gseek-0.2.0/tests/integration/test_m3_adapters.py +165 -0
- gseek-0.2.0/tests/integration/test_m4_adapters.py +144 -0
- gseek-0.2.0/tests/integration/test_replay_matrix.py +105 -0
- gseek-0.2.0/tests/parity/test_real_tool_fixtures.py +278 -0
- gseek-0.2.0/tests/test_adapter_helpers.py +74 -0
- gseek-0.2.0/tests/test_adapter_more.py +153 -0
- gseek-0.2.0/tests/test_adapter_validation.py +88 -0
- gseek-0.2.0/tests/test_api.py +110 -0
- gseek-0.2.0/tests/test_blast_adapter.py +422 -0
- gseek-0.2.0/tests/test_bwa_adapter.py +294 -0
- gseek-0.2.0/tests/test_cli.py +121 -0
- gseek-0.2.0/tests/test_cli_more.py +182 -0
- gseek-0.2.0/tests/test_distance.py +37 -0
- gseek-0.2.0/tests/test_docs.py +48 -0
- gseek-0.2.0/tests/test_docs_links.py +26 -0
- gseek-0.2.0/tests/test_execution.py +146 -0
- gseek-0.2.0/tests/test_execution_more.py +208 -0
- gseek-0.2.0/tests/test_index.py +168 -0
- gseek-0.2.0/tests/test_index_more.py +185 -0
- gseek-0.2.0/tests/test_io.py +129 -0
- gseek-0.2.0/tests/test_io_more.py +110 -0
- gseek-0.2.0/tests/test_kma_adapter.py +273 -0
- gseek-0.2.0/tests/test_mash_adapter.py +262 -0
- gseek-0.2.0/tests/test_minimap2_adapter.py +312 -0
- gseek-0.2.0/tests/test_model.py +231 -0
- gseek-0.2.0/tests/test_model_more.py +203 -0
- gseek-0.2.0/tests/test_mummer_adapter.py +308 -0
- gseek-0.2.0/tests/test_project_identity.py +78 -0
- gseek-0.2.0/tests/test_properties.py +28 -0
- gseek-0.2.0/tests/test_provenance.py +144 -0
- gseek-0.2.0/tests/test_registry.py +76 -0
- gseek-0.2.0/tests/test_registry_builtins.py +97 -0
- gseek-0.2.0/tests/test_registry_more.py +91 -0
- gseek-0.2.0/tests/test_replay.py +188 -0
- gseek-0.2.0/tests/test_runner.py +334 -0
- gseek-0.2.0/tests/test_skani_adapter.py +186 -0
- gseek-0.2.0/tests/test_sourmash_adapter.py +313 -0
- gseek-0.2.0/tests/test_types.py +59 -0
- gseek-0.2.0/tests/test_views.py +127 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
root = true
|
|
2
|
+
|
|
3
|
+
[*]
|
|
4
|
+
charset = utf-8
|
|
5
|
+
end_of_line = lf
|
|
6
|
+
insert_final_newline = true
|
|
7
|
+
trim_trailing_whitespace = true
|
|
8
|
+
indent_style = space
|
|
9
|
+
indent_size = 4
|
|
10
|
+
|
|
11
|
+
[*.{md,markdown,yml,yaml,json,toml}]
|
|
12
|
+
indent_size = 2
|
|
13
|
+
|
|
14
|
+
[*.{diff,patch}]
|
|
15
|
+
trim_trailing_whitespace = false
|
|
16
|
+
|
|
17
|
+
[Makefile]
|
|
18
|
+
indent_style = tab
|
gseek-0.2.0/.gitignore
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# pixi environments
|
|
2
|
+
.pixi/*
|
|
3
|
+
!.pixi/config.toml
|
|
4
|
+
|
|
5
|
+
# Python
|
|
6
|
+
__pycache__/
|
|
7
|
+
*.py[cod]
|
|
8
|
+
*.egg-info/
|
|
9
|
+
.eggs/
|
|
10
|
+
build/
|
|
11
|
+
dist/
|
|
12
|
+
.venv/
|
|
13
|
+
venv/
|
|
14
|
+
pip-wheel-metadata/
|
|
15
|
+
.uv-cache/
|
|
16
|
+
.uv/
|
|
17
|
+
|
|
18
|
+
# Tool caches and local scratch
|
|
19
|
+
.scratch/
|
|
20
|
+
.pytest_cache/
|
|
21
|
+
.ruff_cache/
|
|
22
|
+
.pyright/
|
|
23
|
+
.mypy_cache/
|
|
24
|
+
.hypothesis/
|
|
25
|
+
.benchmarks/
|
|
26
|
+
.tox/
|
|
27
|
+
.nox/
|
|
28
|
+
.coverage
|
|
29
|
+
.coverage.*
|
|
30
|
+
coverage.xml
|
|
31
|
+
coverage.json
|
|
32
|
+
htmlcov/
|
|
33
|
+
|
|
34
|
+
# Local environment/secrets
|
|
35
|
+
.env
|
|
36
|
+
.env.*
|
|
37
|
+
!.env.example
|
|
38
|
+
.direnv/
|
|
39
|
+
AGENTS.local.md
|
|
40
|
+
*.log
|
|
41
|
+
*.prof
|
|
42
|
+
|
|
43
|
+
# Docs
|
|
44
|
+
site/
|
|
45
|
+
docs-site/
|
|
46
|
+
_build/
|
|
47
|
+
|
|
48
|
+
# Editors
|
|
49
|
+
.idea/
|
|
50
|
+
.vscode/
|
|
51
|
+
*.code-workspace
|
|
52
|
+
*.swp
|
|
53
|
+
*.swo
|
|
54
|
+
.DS_Store
|
|
55
|
+
|
|
56
|
+
# Patch leftovers
|
|
57
|
+
*.orig
|
|
58
|
+
*.rej
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
default_install_hook_types: [pre-commit, pre-push]
|
|
2
|
+
default_stages: [pre-commit]
|
|
3
|
+
exclude: ^pixi\.lock$
|
|
4
|
+
|
|
5
|
+
repos:
|
|
6
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
7
|
+
rev: v5.0.0
|
|
8
|
+
hooks:
|
|
9
|
+
- id: check-yaml
|
|
10
|
+
- id: check-toml
|
|
11
|
+
- id: check-added-large-files
|
|
12
|
+
args: [--maxkb=1000]
|
|
13
|
+
- id: check-merge-conflict
|
|
14
|
+
- id: debug-statements
|
|
15
|
+
- id: end-of-file-fixer
|
|
16
|
+
- id: trailing-whitespace
|
|
17
|
+
args: [--markdown-linebreak-ext=md]
|
|
18
|
+
- id: mixed-line-ending
|
|
19
|
+
args: [--fix=lf]
|
|
20
|
+
|
|
21
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
22
|
+
rev: v0.17.1
|
|
23
|
+
hooks:
|
|
24
|
+
- id: ruff
|
|
25
|
+
args: [--fix]
|
|
26
|
+
- id: ruff-format
|
|
27
|
+
|
|
28
|
+
- repo: local
|
|
29
|
+
hooks:
|
|
30
|
+
- id: pytest
|
|
31
|
+
name: pytest (pre-push)
|
|
32
|
+
entry: pixi run test
|
|
33
|
+
language: system
|
|
34
|
+
pass_filenames: false
|
|
35
|
+
stages: [pre-push]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
gseek-0.2.0/AGENTS.md
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
本文件面向在本仓库工作的 AI agent 与人类贡献者。它定义**不可协商的工程约定**。开始任何任务前,先读:
|
|
4
|
+
|
|
5
|
+
1. `README.md`
|
|
6
|
+
2. `docs/api.md`
|
|
7
|
+
3. `dev/development-plan.md`
|
|
8
|
+
4. `dev/adapter-matrix.md`
|
|
9
|
+
5. `dev/compatibility.md`
|
|
10
|
+
6. `dev/decisions/` 下的 ADR
|
|
11
|
+
|
|
12
|
+
## 1. 项目身份
|
|
13
|
+
|
|
14
|
+
| 项 | 值 |
|
|
15
|
+
| --- | --- |
|
|
16
|
+
| 项目名 | **gseek** |
|
|
17
|
+
| 导入包 | `gseek` |
|
|
18
|
+
| PyPI 分发名 | `gseek` |
|
|
19
|
+
| CLI | `gseek` |
|
|
20
|
+
| Python | `>=3.12` |
|
|
21
|
+
| 运行时依赖 | **零**(stdlib only) |
|
|
22
|
+
| 原项目名 | `gcore`(因 PyPI 名称被 Gcore 占用,2026-10-22 更名) |
|
|
23
|
+
|
|
24
|
+
不要在新增代码、文档、schema、环境变量中重新引入 `gcore`。更名细节见 `dev/decisions/0002-project-rename.md`。
|
|
25
|
+
|
|
26
|
+
## 2. 当前状态
|
|
27
|
+
|
|
28
|
+
- M0 基座 + M1/M2/M3/M4 适配器完成:结果模型、执行层、索引缓存、manifest、Runner、API、CLI。
|
|
29
|
+
- `gseek backends` 现在包含 **blast**、**minimap2**、**kma**、**mummer**、**bwa**、**mash**、**sourmash**、**skani**;真实工具集成测试通过。
|
|
30
|
+
- BLAST 支持核酸与蛋白任务;mash 支持 dist/screen;sourmash 支持 search/gather;`gseek replay` 已实现。
|
|
31
|
+
- 消费者迁移/parity(gside/gapit/gmlst)与 1.0 发布尚未完成。
|
|
32
|
+
|
|
33
|
+
## 3. TDD 是强制流程
|
|
34
|
+
|
|
35
|
+
**没有失败的测试,不写生产代码。**
|
|
36
|
+
|
|
37
|
+
### 3.1 Red-Green-Refactor
|
|
38
|
+
|
|
39
|
+
每个行为变更按以下顺序:
|
|
40
|
+
|
|
41
|
+
1. **Red**:先写一个最小测试,表达期望行为。
|
|
42
|
+
- 新功能:`tests/test_<area>.py::test_<behavior>`
|
|
43
|
+
- Bug 修复:先写复现该 bug 的回归测试
|
|
44
|
+
- 重命名/重构:先写“新契约”测试(例如 `tests/test_project_identity.py`)
|
|
45
|
+
2. **确认失败**:运行该测试,确认失败原因是“行为缺失”,不是拼写/导入/夹具错误。
|
|
46
|
+
```bash
|
|
47
|
+
pixi run test tests/test_area.py::test_behavior
|
|
48
|
+
```
|
|
49
|
+
如果测试因为错误原因失败,先修测试。
|
|
50
|
+
3. **Green**:写**最少**的生产代码让该测试通过。不要顺手实现未测试的功能。
|
|
51
|
+
4. **确认通过**:只跑目标测试 + 相关模块测试。
|
|
52
|
+
5. **Refactor**:在测试全绿的前提下重构,保持行为不变。
|
|
53
|
+
6. **全量门禁**:
|
|
54
|
+
```bash
|
|
55
|
+
pixi run check
|
|
56
|
+
```
|
|
57
|
+
必须同时通过 `ruff`、`pyright`、全部 `pytest`。
|
|
58
|
+
|
|
59
|
+
### 3.2 例外
|
|
60
|
+
|
|
61
|
+
- 纯文档、注释、README、ADR:不需要生产代码测试,但必须更新相关文档链接。
|
|
62
|
+
- 纯配置(CI、pixi、pre-commit):如果影响构建/测试行为,先加一个验证命令或测试。
|
|
63
|
+
- 纯格式化:可以在测试绿的前提下直接执行,随后跑全量门禁。
|
|
64
|
+
|
|
65
|
+
### 3.3 适配器开发的 TDD 顺序
|
|
66
|
+
|
|
67
|
+
实现一个适配器时,测试顺序固定:
|
|
68
|
+
|
|
69
|
+
1. `BackendSpec` 能力/工具/版本约束测试。
|
|
70
|
+
2. 命令规划测试(argv、cwd、env、输出路径、超时)。
|
|
71
|
+
3. 解析器 golden 测试(真实输出 fixture,含反向、gapped、空结果、CRLF)。
|
|
72
|
+
4. 坐标/identity/coverage 归一化测试。
|
|
73
|
+
5. 索引 key / artifacts 测试。
|
|
74
|
+
6. 集成测试(`@pytest.mark.integration`,无工具时 skip)。
|
|
75
|
+
7. 消费者 parity 测试(gmlst/gapit/gside 的现有 golden)。
|
|
76
|
+
|
|
77
|
+
只写命令规划、不写解析,或只写解析、不写错误路径,都不算完成。
|
|
78
|
+
|
|
79
|
+
## 4. 架构边界
|
|
80
|
+
|
|
81
|
+
```text
|
|
82
|
+
api → runner → adapters → execution / index / io / model
|
|
83
|
+
│
|
|
84
|
+
└→ capabilities / errors
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
必须遵守:
|
|
88
|
+
|
|
89
|
+
1. **只有 `execution.py` 启动子进程。** 适配器不得直接 `subprocess`。
|
|
90
|
+
2. **适配器是纯规划器/解析器。** `plan_index`/`plan_align` 返回命令;`parse_align` 返回记录。
|
|
91
|
+
3. **不做业务结论。** 不实现 allele calling、ST 查找、物种规则、抗性判定。
|
|
92
|
+
4. **不丢原始记录。** 归并是显式视图(`best_per_query_target`、`deduplicate_intervals` 等)。
|
|
93
|
+
5. **坐标统一。** 0-based half-open、正向序列坐标、strand 单独字段。
|
|
94
|
+
6. **identity/coverage 带来源。** 保留 `identity_method`、原始 `NM`/`nmatch`/`alen`。
|
|
95
|
+
7. **索引内容寻址。** 不用 mtime;key 包含 adapter 版本、语义参数、target 内容哈希、工具版本。
|
|
96
|
+
8. **默认确定性。** 无 shell、绝对路径、`LC_ALL=C`、稳定排序。
|
|
97
|
+
9. **零运行时依赖。** 新增第三方库必须先有 ADR;可选功能放 extras。
|
|
98
|
+
10. **schema 版本化。** `gseek.alignment/1`、`gseek.run/1` 等;破坏性变更升版本。
|
|
99
|
+
|
|
100
|
+
## 5. MUMmer 版本决策
|
|
101
|
+
|
|
102
|
+
**目标:MUMmer 4.x,不是 MUMmer 3。**
|
|
103
|
+
|
|
104
|
+
依据:
|
|
105
|
+
|
|
106
|
+
- `gmlst` 的 pixi 依赖为 `mummer4 = ">=4.0"`。
|
|
107
|
+
- 当前测试环境 conda 包:`mummer4-4.0.1-pl5321h9948957_0`。
|
|
108
|
+
- `nucmer --version` 与 `mummer --version` 均输出 `4.0.1`。
|
|
109
|
+
- `show-coords -rcl -T` 的 MUMmer4 输出为 13 列(`[TAGS]` 表头 + 两个 tag 列)。
|
|
110
|
+
|
|
111
|
+
适配器要求:
|
|
112
|
+
|
|
113
|
+
- `ToolRequirement(binary="nucmer", version_args=("--version",), min_version=(4, 0, 0))`。
|
|
114
|
+
- 使用 `nucmer` + `show-coords -rcl -T`,不依赖 MUMmer3 的旧参数/输出。
|
|
115
|
+
- MUMmer3 不在 1.0 范围内;如需支持,新增独立适配器与 ADR,不要在同一解析器里猜版本。
|
|
116
|
+
- 反向命中用 `S2 > E2` 判断,不能硬编码 `+`。
|
|
117
|
+
|
|
118
|
+
决策记录:`dev/decisions/0001-mummer4.md`。
|
|
119
|
+
|
|
120
|
+
## 6. 代码规范
|
|
121
|
+
|
|
122
|
+
- 行宽 100;`ruff` 规则 `E,W,F,I,UP,B,C4,SIM,RET,RUF`;`ruff format`。
|
|
123
|
+
- 类型:`pyright` standard 必须 0 error;新增核心模块尽量使用精确类型,避免 `Any`。
|
|
124
|
+
- 公共 API 必须有 docstring 与 `__all__`。
|
|
125
|
+
- 单文件建议 ≤ 350 行;超过时按职责拆分。
|
|
126
|
+
- 使用 `pathlib.Path`,不要拼字符串路径。
|
|
127
|
+
- 异常使用 `gseek.errors` 的类型化错误;不要抛裸 `RuntimeError`。
|
|
128
|
+
- 测试使用 `tmp_path`;单元测试不得依赖网络或外部二进制。
|
|
129
|
+
- 需要外部工具的测试标记 `@pytest.mark.integration`,无工具时 `pytest.skip`。
|
|
130
|
+
|
|
131
|
+
## 7. 目录约定
|
|
132
|
+
|
|
133
|
+
```text
|
|
134
|
+
src/gseek/
|
|
135
|
+
├── api.py # 便捷入口
|
|
136
|
+
├── adapter.py # 请求/计划/协议
|
|
137
|
+
├── capabilities.py # 能力声明
|
|
138
|
+
├── execution.py # 唯一子进程层
|
|
139
|
+
├── index.py # 内容寻址索引
|
|
140
|
+
├── io.py # FASTA/FASTQ
|
|
141
|
+
├── model/ # 结果与 manifest
|
|
142
|
+
├── provenance.py # hash/recipe/manifest
|
|
143
|
+
├── registry.py # 适配器注册
|
|
144
|
+
├── runner.py # 编排
|
|
145
|
+
├── adapters/ # M1–M3 + M4 protein/gather/skani
|
|
146
|
+
└── cli.py
|
|
147
|
+
tests/
|
|
148
|
+
├── test_*.py # 单元/契约
|
|
149
|
+
├── fixtures/ # 真实输出(后续)
|
|
150
|
+
├── parity/ # 消费者 parity(后续)
|
|
151
|
+
└── integration/ # 外部工具(M1–M4 已加入)
|
|
152
|
+
docs/
|
|
153
|
+
└── api.md # 公共 API 参考(用户/适配器作者)
|
|
154
|
+
dev/
|
|
155
|
+
├── development-plan.md
|
|
156
|
+
├── adapter-matrix.md
|
|
157
|
+
├── compatibility.md
|
|
158
|
+
├── research.md
|
|
159
|
+
└── decisions/ # ADR
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## 8. 验证命令
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
pixi install # 首次
|
|
166
|
+
pixi run test # 全量单测
|
|
167
|
+
pixi run test-cov # 覆盖率(fail_under=85)
|
|
168
|
+
pixi run lint # ruff check + format --check
|
|
169
|
+
pixi run typecheck # pyright
|
|
170
|
+
pixi run check # lint + typecheck + test
|
|
171
|
+
pixi run pre-commit # 全部 pre-commit hook
|
|
172
|
+
pixi run test tests/test_x.py::test_y # 目标测试
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
提交前必须:
|
|
176
|
+
|
|
177
|
+
- [ ] 先有失败测试(Red),并确认失败原因。
|
|
178
|
+
- [ ] 目标测试通过(Green)。
|
|
179
|
+
- [ ] `pixi run check` 全绿。
|
|
180
|
+
- [ ] 新行为有测试;bug 有回归测试。
|
|
181
|
+
- [ ] 文档/ADR/CHANGELOG 按需更新。
|
|
182
|
+
- [ ] 没有提交 `dist/`、`.pixi/`、`.scratch/`、缓存或临时文件。
|
|
183
|
+
|
|
184
|
+
## 9. 安全与可复现
|
|
185
|
+
|
|
186
|
+
- 永不使用 `shell=True`;argv 列表逐项传入。
|
|
187
|
+
- replay **不执行 manifest 中的任意 argv**;只按 adapter 重新规划。
|
|
188
|
+
- manifest 不记录密钥;环境变量只记录 allowlist。
|
|
189
|
+
- 所有输出路径必须位于 workspace 或 index staging 内。
|
|
190
|
+
- 不静默吞掉解析错误;错误必须带文件/行号/后端。
|
|
191
|
+
- 外部工具缺失/版本过旧必须给出可操作提示。
|
|
192
|
+
|
|
193
|
+
## 10. 提交与发布
|
|
194
|
+
|
|
195
|
+
- 提交信息用英文、祈使句、短标题;正文说明测试与行为。
|
|
196
|
+
- PR 必须包含:行为说明、测试说明、验证命令、文档影响。
|
|
197
|
+
- 版本遵循 SemVer;1.0 前 API 可调整,但 schema 变更必须记录。
|
|
198
|
+
- 发布前:更新 `CHANGELOG.md`、`src/gseek/version.py`、跑 `pixi run check`、构建 wheel/sdist 并在干净环境安装验证。
|
gseek-0.2.0/CHANGELOG.md
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project uses
|
|
5
|
+
[Semantic Versioning](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [0.2.0] - 2026-10-24
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **0.2.0 release preparation: first PyPI release target.**
|
|
14
|
+
- `gseek.distance(..., external_reference=True)` for pre-built distance
|
|
15
|
+
artifacts: mash `.msh` and sourmash `.sig`/`.zip` are consumed directly,
|
|
16
|
+
without index construction or reference re-sketching. External artifacts are
|
|
17
|
+
recorded as `InputKind.SKETCH`; replay re-passes the flag.
|
|
18
|
+
- mash `reads=True` params append `-m 2 -r` to the query sketch for
|
|
19
|
+
error-filtered FASTQ distance.
|
|
20
|
+
- sourmash gather/search parse `query_name` per row and expose
|
|
21
|
+
`reference_name`, `reference_md5`, and `f_unique_weighted` tags.
|
|
22
|
+
- `gseek distance --external-reference` exposes the pre-built-artifact path in
|
|
23
|
+
the CLI.
|
|
24
|
+
- `gseek --error-format {json,text}`; JSON remains the default for automation,
|
|
25
|
+
text is available for humans.
|
|
26
|
+
- User-facing docs: `docs/index.md`, `docs/quickstart.md`, `docs/cli.md`,
|
|
27
|
+
`docs/errors.md`, plus a relative-link regression test.
|
|
28
|
+
- `AGENTS.md`: mandatory TDD workflow, architecture boundaries, MUMmer4 policy.
|
|
29
|
+
- `CONTRIBUTING.md`, `CHANGELOG.md`, `.editorconfig`, `.pre-commit-config.yaml`.
|
|
30
|
+
- ADR-0001: target MUMmer **4.x**, not MUMmer3.
|
|
31
|
+
- ADR-0002: rename from `gcore` to `gseek`.
|
|
32
|
+
- Project identity tests (`tests/test_project_identity.py`) written before the
|
|
33
|
+
rename, covering import name, schemas, env vars, and CLI.
|
|
34
|
+
- **M1 adapters**:
|
|
35
|
+
- BLAST+ `blastn` adapter with `makeblastdb` target indexes, outfmt-6
|
|
36
|
+
streaming parser, reverse-strand coordinates, gap accounting, target
|
|
37
|
+
filtering, and `index_policy=none` subject mode.
|
|
38
|
+
- minimap2 adapter with explicit presets, PAF streaming parser, FASTA/FASTQ,
|
|
39
|
+
paired reads, primary/secondary filtering, `cg`-based gap counts, and
|
|
40
|
+
target indexes.
|
|
41
|
+
- Built-in adapter registry (`gseek.backends()` now lists `blast` and
|
|
42
|
+
`minimap2`).
|
|
43
|
+
- Prefix index entries (e.g. BLAST `targets` backed by `targets.nhr`) in
|
|
44
|
+
`IndexStore`.
|
|
45
|
+
- **M2 adapters**:
|
|
46
|
+
- KMA adapter with `kma index` target databases, `.res` parsing (no
|
|
47
|
+
coordinates), assembly/FASTQ/paired modes, depth, and template-level
|
|
48
|
+
identity/coverage.
|
|
49
|
+
- MUMmer4 `nucmer` + `show-coords -rcl -T` adapter, multi-step execution,
|
|
50
|
+
reverse-strand coordinates, no persistent index, and explicit MUMmer4
|
|
51
|
+
version gate.
|
|
52
|
+
- Built-in registry now lists `blast`, `minimap2`, `kma`, and `mummer`.
|
|
53
|
+
- **M3 adapters**:
|
|
54
|
+
- BWA-MEM adapter with `bwa index` target prefixes, SAM/CIGAR streaming,
|
|
55
|
+
reverse-strand query intervals, soft-clip accounting, paired reads, and
|
|
56
|
+
secondary/supplementary flags.
|
|
57
|
+
- mash adapter with `mash sketch`, `mash dist`, and reads `screen` mode;
|
|
58
|
+
MinHash distance/containment records.
|
|
59
|
+
- sourmash adapter with DNA sketches, `sourmash search` CSV, and
|
|
60
|
+
Jaccard/containment semantics.
|
|
61
|
+
- CIGAR helper now tracks leading/trailing soft and hard clips.
|
|
62
|
+
- **M4 features**:
|
|
63
|
+
- BLAST protein tasks: `blastp`, `blastx`, `tblastn`, `tblastx`, with
|
|
64
|
+
protein/nucleotide `makeblastdb` selection and SEG defaults.
|
|
65
|
+
- sourmash `gather` mode with `--threshold-bp` and gather CSV parsing.
|
|
66
|
+
- skani ANI adapter with sketch/search databases, ANI and aligned-fraction
|
|
67
|
+
records.
|
|
68
|
+
- Safe `gseek.replay` / `gseek replay` with `result_hash` in run manifests;
|
|
69
|
+
replay never executes recorded argv.
|
|
70
|
+
- Unit/contract tests for all eight adapters, plus real-tool integration tests
|
|
71
|
+
for index reuse, manifest verification, FASTQ mapping, thread invariance,
|
|
72
|
+
KMA paired reads, MUMmer reverse-strand hits, BWA paired reads, mash
|
|
73
|
+
dist/screen, sourmash search/gather, skani ANI, and manifest replay.
|
|
74
|
+
|
|
75
|
+
### Changed
|
|
76
|
+
|
|
77
|
+
- **Renamed the project from `gcore` to `gseek`.** PyPI's `gcore` is already
|
|
78
|
+
owned by the Gcore Python API. Distribution, import package, CLI, environment
|
|
79
|
+
variables (`GSEEK_*`), schemas (`gseek.*`), and plugin entry point group are
|
|
80
|
+
now all `gseek`.
|
|
81
|
+
- `GcoreError` → `GseekError`.
|
|
82
|
+
|
|
83
|
+
### Fixed
|
|
84
|
+
|
|
85
|
+
- `result_hash` is now computed over a canonical total order, so multi-record
|
|
86
|
+
`replay --check` no longer depends on parser or tool output order.
|
|
87
|
+
- `index_policy=rebuild` now actually replaces the published index; the cache
|
|
88
|
+
layer gained `publish(replace=...)` and returns `cache_hit=False` after a
|
|
89
|
+
rebuild.
|
|
90
|
+
- Tool paths resolved by `ToolResolver` (`overrides`, `GSEEK_<BINARY>`,
|
|
91
|
+
`extra_paths`, `GSEEK_PATH_PREPEND`) are bound into `Executor` and used for
|
|
92
|
+
execution; manifest commands now record the absolute executable.
|
|
93
|
+
- Index-only parameters (KMA `-k`, BWA `-a/-b`, skani `-c/-m`) are accepted by
|
|
94
|
+
the alignment/distance planners and no longer make end-to-end runs fail.
|
|
95
|
+
- Manifests record absolute input/target paths; `verify` resolves legacy
|
|
96
|
+
relative paths against the manifest directory, matching `replay`.
|
|
97
|
+
- Corrupt `index.json` values (for example a JSON array) are treated as cache
|
|
98
|
+
misses; `IndexStore(enabled=False)` rejects writes and Runner skips indexing.
|
|
99
|
+
- Probe caching now keys on resolved path/pattern/min_version/role, re-raises
|
|
100
|
+
cached missing tools under `strict=True`, and does not raise for optional
|
|
101
|
+
outdated tools. `BaseAdapter` distinguishes `ToolNotFoundError` from
|
|
102
|
+
`ToolVersionError` and forwards `ToolRequirement.hint`.
|
|
103
|
+
- BLAST always passes `-task` where supported (not `tblastx`), so `blastn` is
|
|
104
|
+
no longer silently megablast; protein tasks reject `-perc_identity`.
|
|
105
|
+
- minimap2 identity prefers `NM` (`paf_nm`) and falls back to `nmatch/alen`
|
|
106
|
+
(`paf_matches`); records expose `identity_from_nm`, `identity_from_matches`,
|
|
107
|
+
and `identity_nmatch_nm` parity views.
|
|
108
|
+
- JSON/TSV and ingestion fixes: deterministic set serialization, truthful
|
|
109
|
+
JSONL footer status, coordinate-less records preserved by
|
|
110
|
+
`deduplicate_intervals`, strict FASTQ record counting, streamed stderr
|
|
111
|
+
capped during drain, and executor-based manifest environment capture.
|
|
112
|
+
- CI integration now installs `skani` and runs nightly in addition to manual
|
|
113
|
+
dispatch.
|
|
114
|
+
- Added `external_reference=True` to `gseek.distance()`: mash/sourmash
|
|
115
|
+
adapters can consume pre-built `.msh`/`.sig`/`.zip` artifacts without
|
|
116
|
+
indexing or re-sketching references. External artifacts are recorded as
|
|
117
|
+
`InputKind.SKETCH` and replay re-passes the flag.
|
|
118
|
+
- Added real-tool golden fixtures under `tests/fixtures/`, field/formula parity
|
|
119
|
+
tests for gside/gapit/gmlst, and an 8-backend real replay matrix. Sourmash
|
|
120
|
+
reference IDs now fall back from signature name to a genome-like filename to
|
|
121
|
+
the unique `md5`, so references inside one combined `.sig` no longer collide.
|
|
122
|
+
|
|
123
|
+
## [0.1.0] - 2026-10-22
|
|
124
|
+
|
|
125
|
+
### Added
|
|
126
|
+
|
|
127
|
+
- Project foundation:
|
|
128
|
+
- `gseek.model`: `AlignmentRecord`, `AlignmentResult`, `DistanceResult`,
|
|
129
|
+
`RunManifest`, `IndexRef`, `CommandRecord`.
|
|
130
|
+
- `gseek.execution`: deterministic subprocess execution, timeouts, streaming,
|
|
131
|
+
stderr draining, tool resolution/version probing.
|
|
132
|
+
- `gseek.index`: content-addressed index cache, file locks, staging + atomic
|
|
133
|
+
publish, GC.
|
|
134
|
+
- `gseek.provenance`: SHA-256, canonical JSON, recipe hash, manifest
|
|
135
|
+
read/write/verify.
|
|
136
|
+
- `gseek.adapter`, `gseek.registry`, `gseek.runner`: adapter protocol,
|
|
137
|
+
registry, end-to-end orchestration.
|
|
138
|
+
- `gseek.api` and `gseek` CLI: align/distance/backends/doctor/index/manifest.
|
|
139
|
+
- Documentation:
|
|
140
|
+
- `docs/api.md`
|
|
141
|
+
- `dev/development-plan.md`
|
|
142
|
+
- `dev/research.md`
|
|
143
|
+
- `dev/adapter-matrix.md`
|
|
144
|
+
- `dev/compatibility.md`
|
|
145
|
+
- 250 unit/contract tests + 21 integration tests; 88% coverage; ruff + pyright clean.
|
|
146
|
+
- MIT license, pixi environment, GitHub Actions CI.
|
|
147
|
+
|
|
148
|
+
### Notes
|
|
149
|
+
|
|
150
|
+
- M1–M4 adapter features (including protein BLAST, gather, skani, replay)
|
|
151
|
+
are implemented. Consumer migration/parity is still pending.
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Contributing to gseek
|
|
2
|
+
|
|
3
|
+
感谢贡献。`gseek` 是 gside/gapit/gmlst 共用的 DNA 比对基础设施;正确性、可复现性和向后兼容比“多写代码”更重要。
|
|
4
|
+
|
|
5
|
+
## 1. 开发环境
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pixi install
|
|
9
|
+
pixi run check
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
需要 Python ≥ 3.12。外部比对工具(BLAST+、minimap2、MUMmer4、KMA、BWA、mash、sourmash)只在集成测试中需要,不随包安装。
|
|
13
|
+
|
|
14
|
+
## 2. TDD:先失败,再实现
|
|
15
|
+
|
|
16
|
+
**没有失败的测试,不写生产代码。** 详细规则见 [AGENTS.md](AGENTS.md)。
|
|
17
|
+
|
|
18
|
+
### 2.1 最小示例
|
|
19
|
+
|
|
20
|
+
假设要新增 `gseek.views.best_per_query`:
|
|
21
|
+
|
|
22
|
+
1. 在 `tests/test_views.py` 写测试:
|
|
23
|
+
```python
|
|
24
|
+
def test_best_per_query_keeps_highest_identity() -> None:
|
|
25
|
+
...
|
|
26
|
+
assert best[0].identity == 99.0
|
|
27
|
+
```
|
|
28
|
+
2. 运行并确认失败:
|
|
29
|
+
```bash
|
|
30
|
+
pixi run test tests/test_views.py::test_best_per_query_keeps_highest_identity
|
|
31
|
+
```
|
|
32
|
+
失败原因必须是 `AttributeError`/`ImportError` 等“功能不存在”,不能是测试写错。
|
|
33
|
+
3. 写最少实现。
|
|
34
|
+
4. 目标测试通过。
|
|
35
|
+
5. 跑全量:
|
|
36
|
+
```bash
|
|
37
|
+
pixi run check
|
|
38
|
+
```
|
|
39
|
+
6. 在绿的前提下重构。
|
|
40
|
+
|
|
41
|
+
### 2.2 Bug 修复
|
|
42
|
+
|
|
43
|
+
先写回归测试,确认它能在当前代码上复现 bug;再修复。禁止“先修再看”。
|
|
44
|
+
|
|
45
|
+
### 2.3 重构/重命名
|
|
46
|
+
|
|
47
|
+
先写新契约测试(例如 `tests/test_project_identity.py` 对 `gseek` 的断言),确认红;再改代码;最后全绿。
|
|
48
|
+
|
|
49
|
+
## 3. 测试分层
|
|
50
|
+
|
|
51
|
+
| 层级 | 位置 | 依赖外部工具 | 说明 |
|
|
52
|
+
| --- | --- | --- | --- |
|
|
53
|
+
| 单元 | `tests/test_*.py` | 否 | 模型、解析、命令规划、hash、index |
|
|
54
|
+
| golden | `tests/fixtures/` | 否 | 真实工具输出,逐字段断言 |
|
|
55
|
+
| 集成 | `tests/integration/` | 是 | `@pytest.mark.integration`,无工具 skip |
|
|
56
|
+
| parity | `tests/parity/` | 部分 | 与 gside/gapit/gmlst 旧模型对比 |
|
|
57
|
+
|
|
58
|
+
要求:
|
|
59
|
+
|
|
60
|
+
- 单元测试不联网、不依赖 PATH 里的工具。
|
|
61
|
+
- 所有临时文件用 `tmp_path`。
|
|
62
|
+
- 不 mock 掉被测逻辑;只 mock 进程边界(`Executor`/resolver)。
|
|
63
|
+
- 解析器测试必须覆盖:正常、反向、gapped、空结果、坏行、CRLF/空白。
|
|
64
|
+
- 新适配器必须包含命令规划测试与真实输出 golden。
|
|
65
|
+
|
|
66
|
+
## 4. 架构红线
|
|
67
|
+
|
|
68
|
+
- 只有 `src/gseek/execution.py` 启动子进程。
|
|
69
|
+
- 适配器只做规划/解析,不做生物学判定。
|
|
70
|
+
- 结果模型无损;归并是显式视图。
|
|
71
|
+
- 坐标 0-based half-open;strand 单独字段。
|
|
72
|
+
- 索引内容寻址,不用 mtime。
|
|
73
|
+
- 核心零运行时依赖。
|
|
74
|
+
- 不使用 `shell=True`。
|
|
75
|
+
- 具体规则见 [AGENTS.md](AGENTS.md)。
|
|
76
|
+
|
|
77
|
+
## 5. 代码风格
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
pixi run format
|
|
81
|
+
pixi run lint
|
|
82
|
+
pixi run typecheck
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
- `ruff` + `ruff format`,行宽 100。
|
|
86
|
+
- `pyright` standard 0 error。
|
|
87
|
+
- 公共 API 写 docstring 和类型注解。
|
|
88
|
+
- 异常使用 `gseek.errors`。
|
|
89
|
+
- 单文件建议 ≤ 350 行。
|
|
90
|
+
|
|
91
|
+
## 6. 文档
|
|
92
|
+
|
|
93
|
+
- 公共 API/行为变化更新 `docs/api.md`;设计/架构说明更新 `dev/` 对应文档。
|
|
94
|
+
- 架构/版本/命名决策写 ADR:`dev/decisions/NNNN-title.md`。
|
|
95
|
+
- 用户可见变化更新 `CHANGELOG.md`。
|
|
96
|
+
- MUMmer:目标为 **MUMmer 4.x**,见 [ADR-0001](dev/decisions/0001-mummer4.md)。
|
|
97
|
+
|
|
98
|
+
## 7. 提交与 PR
|
|
99
|
+
|
|
100
|
+
提交信息用英文祈使句:
|
|
101
|
+
|
|
102
|
+
```text
|
|
103
|
+
Add FASTA duplicate-ID validation
|
|
104
|
+
Fix PAF reverse-strand coordinate normalization
|
|
105
|
+
Rename package to gseek
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
PR 描述包含:
|
|
109
|
+
|
|
110
|
+
1. 行为变化(用户可见)
|
|
111
|
+
2. 测试说明(先失败的测试是哪一个)
|
|
112
|
+
3. 验证命令与结果
|
|
113
|
+
4. 文档/CHANGELOG/ADR 影响
|
|
114
|
+
|
|
115
|
+
## 8. 发布
|
|
116
|
+
|
|
117
|
+
1. 更新 `src/gseek/version.py` 与 `pyproject.toml` 的版本。
|
|
118
|
+
2. 更新 `CHANGELOG.md`。
|
|
119
|
+
3. `pixi run check`。
|
|
120
|
+
4. `python -m build` + `twine check dist/*`。
|
|
121
|
+
5. 在干净 venv 中 `pip install dist/*.whl`,跑 `gseek --version` 和最小 API 冒烟。
|
|
122
|
+
6. 打 tag、发布 PyPI/conda。
|
|
123
|
+
|
|
124
|
+
## 9. 许可证
|
|
125
|
+
|
|
126
|
+
贡献即同意以 MIT 许可证发布。详见 [LICENSE](LICENSE)。
|
gseek-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 gseek contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|