afquery 0.4.1__tar.gz → 0.4.2__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 (168) hide show
  1. {afquery-0.4.1 → afquery-0.4.2}/PKG-INFO +1 -1
  2. {afquery-0.4.1 → afquery-0.4.2}/docs/reference/cli.md +13 -0
  3. {afquery-0.4.1 → afquery-0.4.2}/docs/troubleshooting.md +0 -78
  4. {afquery-0.4.1 → afquery-0.4.2}/src/afquery/_version.py +2 -2
  5. {afquery-0.4.1 → afquery-0.4.2}/src/afquery/cli.py +12 -7
  6. {afquery-0.4.1 → afquery-0.4.2}/tests/test_cli.py +23 -0
  7. {afquery-0.4.1 → afquery-0.4.2}/.dockerignore +0 -0
  8. {afquery-0.4.1 → afquery-0.4.2}/.github/workflows/ci.yml +0 -0
  9. {afquery-0.4.1 → afquery-0.4.2}/.github/workflows/docs.yml +0 -0
  10. {afquery-0.4.1 → afquery-0.4.2}/.github/workflows/release.yml +0 -0
  11. {afquery-0.4.1 → afquery-0.4.2}/.gitignore +0 -0
  12. {afquery-0.4.1 → afquery-0.4.2}/CONTRIBUTING.md +0 -0
  13. {afquery-0.4.1 → afquery-0.4.2}/Dockerfile +0 -0
  14. {afquery-0.4.1 → afquery-0.4.2}/LICENSE +0 -0
  15. {afquery-0.4.1 → afquery-0.4.2}/README.md +0 -0
  16. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/.gitignore +0 -0
  17. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/INSTALL.md +0 -0
  18. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/README.md +0 -0
  19. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/Snakefile +0 -0
  20. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/capture_kit/.gitignore +0 -0
  21. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/capture_kit/01a_assign_samples.py +0 -0
  22. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/capture_kit/01b_write_manifests.py +0 -0
  23. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/capture_kit/02_build_databases.py +0 -0
  24. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/capture_kit/03_compute_metrics.py +0 -0
  25. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/capture_kit/04_classify_acmg.py +0 -0
  26. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/capture_kit/05_plot_figures.py +0 -0
  27. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/capture_kit/README.md +0 -0
  28. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/capture_kit/Snakefile +0 -0
  29. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/capture_kit/__init__.py +0 -0
  30. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/capture_kit/beds/SureSelect_v5.bed +0 -0
  31. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/capture_kit/beds/SureSelect_v6.bed +0 -0
  32. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/capture_kit/beds/SureSelect_v7.bed +0 -0
  33. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/capture_kit/config.py +0 -0
  34. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/config.yaml +0 -0
  35. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/envs/benchmark.yaml +0 -0
  36. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/performance/.gitignore +0 -0
  37. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/performance/01_prepare_data.py +0 -0
  38. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/performance/02_query_scaling.py +0 -0
  39. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/performance/03_build.py +0 -0
  40. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/performance/04_annotate.py +0 -0
  41. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/performance/05_vs_bcftools.py +0 -0
  42. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/performance/06_plot.py +0 -0
  43. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/performance/README.md +0 -0
  44. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/performance/Snakefile +0 -0
  45. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/performance/collect_annotate.py +0 -0
  46. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/performance/collect_bcftools.py +0 -0
  47. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/performance/collect_build_perf.py +0 -0
  48. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/performance/collect_prepare.py +0 -0
  49. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/performance/collect_query_scaling.py +0 -0
  50. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/performance/config.py +0 -0
  51. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/performance/config_smoke.py +0 -0
  52. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/shared/__init__.py +0 -0
  53. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/shared/config.py +0 -0
  54. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/shared/rules/download_1kg.smk +0 -0
  55. {afquery-0.4.1 → afquery-0.4.2}/benchmarks/shared/utils.py +0 -0
  56. {afquery-0.4.1 → afquery-0.4.2}/docs/advanced/benchmarking.md +0 -0
  57. {afquery-0.4.1 → afquery-0.4.2}/docs/advanced/coverage-evidence.md +0 -0
  58. {afquery-0.4.1 → afquery-0.4.2}/docs/advanced/debugging-results.md +0 -0
  59. {afquery-0.4.1 → afquery-0.4.2}/docs/advanced/filter-pass-tracking.md +0 -0
  60. {afquery-0.4.1 → afquery-0.4.2}/docs/advanced/multi-cohort-strategies.md +0 -0
  61. {afquery-0.4.1 → afquery-0.4.2}/docs/advanced/performance.md +0 -0
  62. {afquery-0.4.1 → afquery-0.4.2}/docs/advanced/pipeline-integration.md +0 -0
  63. {afquery-0.4.1 → afquery-0.4.2}/docs/advanced/ploidy-and-sex-chroms.md +0 -0
  64. {afquery-0.4.1 → afquery-0.4.2}/docs/assets/img/gap2_mixed_technologies.png +0 -0
  65. {afquery-0.4.1 → afquery-0.4.2}/docs/faq.md +0 -0
  66. {afquery-0.4.1 → afquery-0.4.2}/docs/getting-started/concepts.md +0 -0
  67. {afquery-0.4.1 → afquery-0.4.2}/docs/getting-started/installation.md +0 -0
  68. {afquery-0.4.1 → afquery-0.4.2}/docs/getting-started/motivation.md +0 -0
  69. {afquery-0.4.1 → afquery-0.4.2}/docs/getting-started/preprocessing.md +0 -0
  70. {afquery-0.4.1 → afquery-0.4.2}/docs/getting-started/quickstart.md +0 -0
  71. {afquery-0.4.1 → afquery-0.4.2}/docs/getting-started/tutorial.md +0 -0
  72. {afquery-0.4.1 → afquery-0.4.2}/docs/getting-started/understanding-output.md +0 -0
  73. {afquery-0.4.1 → afquery-0.4.2}/docs/guides/annotate-vcf.md +0 -0
  74. {afquery-0.4.1 → afquery-0.4.2}/docs/guides/create-database.md +0 -0
  75. {afquery-0.4.1 → afquery-0.4.2}/docs/guides/dump-export.md +0 -0
  76. {afquery-0.4.1 → afquery-0.4.2}/docs/guides/manifest-format.md +0 -0
  77. {afquery-0.4.1 → afquery-0.4.2}/docs/guides/query.md +0 -0
  78. {afquery-0.4.1 → afquery-0.4.2}/docs/guides/sample-filtering.md +0 -0
  79. {afquery-0.4.1 → afquery-0.4.2}/docs/guides/update-database.md +0 -0
  80. {afquery-0.4.1 → afquery-0.4.2}/docs/guides/variant-info.md +0 -0
  81. {afquery-0.4.1 → afquery-0.4.2}/docs/index.md +0 -0
  82. {afquery-0.4.1 → afquery-0.4.2}/docs/reference/data-model.md +0 -0
  83. {afquery-0.4.1 → afquery-0.4.2}/docs/reference/glossary.md +0 -0
  84. {afquery-0.4.1 → afquery-0.4.2}/docs/reference/python-api.md +0 -0
  85. {afquery-0.4.1 → afquery-0.4.2}/docs/scripts/gen_gap2_figure.py +0 -0
  86. {afquery-0.4.1 → afquery-0.4.2}/docs/stylesheets/extra.css +0 -0
  87. {afquery-0.4.1 → afquery-0.4.2}/docs/use-cases/acmg-use-cases.md +0 -0
  88. {afquery-0.4.1 → afquery-0.4.2}/docs/use-cases/clinical-prioritization.md +0 -0
  89. {afquery-0.4.1 → afquery-0.4.2}/docs/use-cases/cohort-stratification.md +0 -0
  90. {afquery-0.4.1 → afquery-0.4.2}/docs/use-cases/population-specific-af.md +0 -0
  91. {afquery-0.4.1 → afquery-0.4.2}/docs/use-cases/pseudo-controls.md +0 -0
  92. {afquery-0.4.1 → afquery-0.4.2}/docs/use-cases/sex-specific-af.md +0 -0
  93. {afquery-0.4.1 → afquery-0.4.2}/docs/use-cases/technology-integration.md +0 -0
  94. {afquery-0.4.1 → afquery-0.4.2}/examples/demo/README.md +0 -0
  95. {afquery-0.4.1 → afquery-0.4.2}/examples/demo/create_demo_data.py +0 -0
  96. {afquery-0.4.1 → afquery-0.4.2}/mkdocs.yml +0 -0
  97. {afquery-0.4.1 → afquery-0.4.2}/pyproject.toml +0 -0
  98. {afquery-0.4.1 → afquery-0.4.2}/recipes/afquery/meta.yaml +0 -0
  99. {afquery-0.4.1 → afquery-0.4.2}/resources/normalize_vcf.sh +0 -0
  100. {afquery-0.4.1 → afquery-0.4.2}/src/afquery/__init__.py +0 -0
  101. {afquery-0.4.1 → afquery-0.4.2}/src/afquery/annotate.py +0 -0
  102. {afquery-0.4.1 → afquery-0.4.2}/src/afquery/benchmark.py +0 -0
  103. {afquery-0.4.1 → afquery-0.4.2}/src/afquery/bitmaps.py +0 -0
  104. {afquery-0.4.1 → afquery-0.4.2}/src/afquery/capture.py +0 -0
  105. {afquery-0.4.1 → afquery-0.4.2}/src/afquery/cli.pyr +0 -0
  106. {afquery-0.4.1 → afquery-0.4.2}/src/afquery/constants.py +0 -0
  107. {afquery-0.4.1 → afquery-0.4.2}/src/afquery/database.py +0 -0
  108. {afquery-0.4.1 → afquery-0.4.2}/src/afquery/dump.py +0 -0
  109. {afquery-0.4.1 → afquery-0.4.2}/src/afquery/models.py +0 -0
  110. {afquery-0.4.1 → afquery-0.4.2}/src/afquery/ploidy.py +0 -0
  111. {afquery-0.4.1 → afquery-0.4.2}/src/afquery/preprocess/__init__.py +0 -0
  112. {afquery-0.4.1 → afquery-0.4.2}/src/afquery/preprocess/build.py +0 -0
  113. {afquery-0.4.1 → afquery-0.4.2}/src/afquery/preprocess/compact.py +0 -0
  114. {afquery-0.4.1 → afquery-0.4.2}/src/afquery/preprocess/ingest.py +0 -0
  115. {afquery-0.4.1 → afquery-0.4.2}/src/afquery/preprocess/manifest.py +0 -0
  116. {afquery-0.4.1 → afquery-0.4.2}/src/afquery/preprocess/regions.py +0 -0
  117. {afquery-0.4.1 → afquery-0.4.2}/src/afquery/preprocess/synth.py +0 -0
  118. {afquery-0.4.1 → afquery-0.4.2}/src/afquery/preprocess/update.py +0 -0
  119. {afquery-0.4.1 → afquery-0.4.2}/src/afquery/query.py +0 -0
  120. {afquery-0.4.1 → afquery-0.4.2}/src/afquery/storage.py +0 -0
  121. {afquery-0.4.1 → afquery-0.4.2}/src/afquery/variant_info.py +0 -0
  122. {afquery-0.4.1 → afquery-0.4.2}/tests/conftest.py +0 -0
  123. {afquery-0.4.1 → afquery-0.4.2}/tests/data/annotate_input.vcf +0 -0
  124. {afquery-0.4.1 → afquery-0.4.2}/tests/data/annotate_multi_bucket.vcf +0 -0
  125. {afquery-0.4.1 → afquery-0.4.2}/tests/data/annotate_multi_chrom.vcf +0 -0
  126. {afquery-0.4.1 → afquery-0.4.2}/tests/data/beds/wes_kit_a.bed +0 -0
  127. {afquery-0.4.1 → afquery-0.4.2}/tests/data/beds/wes_kit_b.bed +0 -0
  128. {afquery-0.4.1 → afquery-0.4.2}/tests/data/beds/wes_kit_nochr.bed +0 -0
  129. {afquery-0.4.1 → afquery-0.4.2}/tests/data/expected_results.json +0 -0
  130. {afquery-0.4.1 → afquery-0.4.2}/tests/data/manifest.tsv +0 -0
  131. {afquery-0.4.1 → afquery-0.4.2}/tests/data/vcfs/S00.vcf +0 -0
  132. {afquery-0.4.1 → afquery-0.4.2}/tests/data/vcfs/S01.vcf +0 -0
  133. {afquery-0.4.1 → afquery-0.4.2}/tests/data/vcfs/S02.vcf +0 -0
  134. {afquery-0.4.1 → afquery-0.4.2}/tests/data/vcfs/S03.vcf +0 -0
  135. {afquery-0.4.1 → afquery-0.4.2}/tests/data/vcfs/S04.vcf +0 -0
  136. {afquery-0.4.1 → afquery-0.4.2}/tests/data/vcfs/S05.vcf +0 -0
  137. {afquery-0.4.1 → afquery-0.4.2}/tests/data/vcfs/S06.vcf +0 -0
  138. {afquery-0.4.1 → afquery-0.4.2}/tests/data/vcfs/S07.vcf +0 -0
  139. {afquery-0.4.1 → afquery-0.4.2}/tests/data/vcfs/S08.vcf +0 -0
  140. {afquery-0.4.1 → afquery-0.4.2}/tests/data/vcfs/S09.vcf +0 -0
  141. {afquery-0.4.1 → afquery-0.4.2}/tests/oracle.py +0 -0
  142. {afquery-0.4.1 → afquery-0.4.2}/tests/test_annotate.py +0 -0
  143. {afquery-0.4.1 → afquery-0.4.2}/tests/test_batch.py +0 -0
  144. {afquery-0.4.1 → afquery-0.4.2}/tests/test_benchmark.py +0 -0
  145. {afquery-0.4.1 → afquery-0.4.2}/tests/test_bitmaps.py +0 -0
  146. {afquery-0.4.1 → afquery-0.4.2}/tests/test_capture.py +0 -0
  147. {afquery-0.4.1 → afquery-0.4.2}/tests/test_cli_docs_consistency.py +0 -0
  148. {afquery-0.4.1 → afquery-0.4.2}/tests/test_compact.py +0 -0
  149. {afquery-0.4.1 → afquery-0.4.2}/tests/test_constants.py +0 -0
  150. {afquery-0.4.1 → afquery-0.4.2}/tests/test_dump.py +0 -0
  151. {afquery-0.4.1 → afquery-0.4.2}/tests/test_haploid_stats.py +0 -0
  152. {afquery-0.4.1 → afquery-0.4.2}/tests/test_info.py +0 -0
  153. {afquery-0.4.1 → afquery-0.4.2}/tests/test_invariants.py +0 -0
  154. {afquery-0.4.1 → afquery-0.4.2}/tests/test_no_coverage.py +0 -0
  155. {afquery-0.4.1 → afquery-0.4.2}/tests/test_oracle_consistency.py +0 -0
  156. {afquery-0.4.1 → afquery-0.4.2}/tests/test_pass_filter.py +0 -0
  157. {afquery-0.4.1 → afquery-0.4.2}/tests/test_ploidy.py +0 -0
  158. {afquery-0.4.1 → afquery-0.4.2}/tests/test_preprocess.py +0 -0
  159. {afquery-0.4.1 → afquery-0.4.2}/tests/test_query.py +0 -0
  160. {afquery-0.4.1 → afquery-0.4.2}/tests/test_sample_filter.py +0 -0
  161. {afquery-0.4.1 → afquery-0.4.2}/tests/test_storage.py +0 -0
  162. {afquery-0.4.1 → afquery-0.4.2}/tests/test_synth.py +0 -0
  163. {afquery-0.4.1 → afquery-0.4.2}/tests/test_synthetic_stats.py +0 -0
  164. {afquery-0.4.1 → afquery-0.4.2}/tests/test_update.py +0 -0
  165. {afquery-0.4.1 → afquery-0.4.2}/tests/test_update_metadata.py +0 -0
  166. {afquery-0.4.1 → afquery-0.4.2}/tests/test_update_partitioned.py +0 -0
  167. {afquery-0.4.1 → afquery-0.4.2}/tests/test_variant_info.py +0 -0
  168. {afquery-0.4.1 → afquery-0.4.2}/tests/test_warnings.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: afquery
3
- Version: 0.4.1
3
+ Version: 0.4.2
4
4
  Summary: Genomic allele frequency query engine with bitmap-encoded genotypes
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -4,6 +4,19 @@ All AFQuery commands follow the pattern `afquery <command> [OPTIONS]`.
4
4
 
5
5
  ---
6
6
 
7
+ ## Global options
8
+
9
+ | Option | Description |
10
+ |--------|-------------|
11
+ | `--version` | Print the AFQuery version and exit |
12
+ | `--help` | Show help for the command and exit |
13
+
14
+ `afquery --version` prints the installed package version (e.g. `afquery 0.4.2`),
15
+ taken from the Git release tag at build time. In an editable install
16
+ (`pip install -e .`) it reflects the last build, not later local commits.
17
+
18
+ ---
19
+
7
20
  ## create-db
8
21
 
9
22
  Build a new AFQuery database from a manifest of single-sample VCFs.
@@ -81,84 +81,6 @@ AFQuery requires DuckDB to use Parquet for all temporary files. Arrow IPC is not
81
81
 
82
82
  ---
83
83
 
84
- ## Samples Added by update-db Are Missing From Queries
85
-
86
- **Symptom:** After `afquery update-db --add-samples`, the new samples show up in
87
- `afquery info --db ./db/ --samples` and `AN` grows by the expected amount, but they
88
- never appear as carriers: `AC` does not increase at variants you know they carry, and
89
- `afquery variant-info` does not list them. Allele frequencies across the whole database
90
- drift downward after every update.
91
-
92
- `afquery check --db ./db/` reports one error per affected chromosome:
93
-
94
- ```
95
- ERROR chr1: both variants/chr1/ (bucketed) and variants/chr1.parquet exist.
96
- ```
97
-
98
- **Cause:** `update-db --add-samples` before 0.4.1 only understood the
99
- single-file-per-chromosome variant layout. `create-db` produces the bucketed layout
100
- (`variants/<chrom>/bucket_N.parquet`), so the merge found nothing to merge and wrote the
101
- new samples to a fresh `variants/<chrom>.parquet` instead. Queries read the bucketed
102
- files and ignore that one, so the added samples counted toward `AN` through the capture
103
- index but never as carriers — they were treated as homozygous reference everywhere.
104
-
105
- **Fix:** Upgrade to 0.4.1 or later, then repair the database. `afquery info --db ./db/
106
- --changelog` lists the samples added by each `add_samples` event.
107
-
108
- ```bash
109
- # 0. Stop all writers and back up the small files.
110
- cp ./db/manifest.json ./db/manifest.json.bak
111
- cp ./db/metadata.sqlite ./db/metadata.sqlite.bak
112
-
113
- # 1. Record the affected samples BEFORE removing them: removal deletes their
114
- # phenotype rows, and you need them to rebuild the manifest.
115
- sqlite3 ./db/metadata.sqlite \
116
- "SELECT s.sample_name, s.sex, t.tech_name, s.vcf_path,
117
- group_concat(p.phenotype_code)
118
- FROM samples s
119
- JOIN technologies t ON s.tech_id = t.tech_id
120
- LEFT JOIN sample_phenotype p ON p.sample_id = s.sample_id
121
- WHERE s.sample_name IN ('SAMPLE_1','SAMPLE_2') GROUP BY s.sample_id;"
122
-
123
- # 2. List the flat files before deleting anything. Only those with a sibling
124
- # directory of the same name are orphans; one without a sibling is the only
125
- # copy of that chromosome and queries still read it.
126
- for f in ./db/variants/*.parquet; do
127
- [ -d "${f%.parquet}" ] && echo "orphan: $f" || echo "KEEP (no sibling): $f"
128
- done
129
-
130
- # 3. Remove the affected samples. This clears their bits from both layouts and is
131
- # safe on a split database. Every bucket is read, so budget minutes, not
132
- # seconds, and do not interrupt it.
133
- afquery update-db --db ./db/ --remove-samples SAMPLE_1 --remove-samples SAMPLE_2
134
-
135
- # 4. Delete only the orphans listed in step 2. A flat file with no sibling
136
- # directory must be kept: deleting it would drop that chromosome entirely.
137
- for f in ./db/variants/*.parquet; do
138
- [ -d "${f%.parquet}" ] && rm "$f"
139
- done
140
-
141
- # 5. Confirm the errors are gone.
142
- afquery check --db ./db/
143
-
144
- # 6. Re-add the samples with the fixed version.
145
- afquery update-db --db ./db/ --add-samples repair.tsv --bed-dir ./beds/
146
-
147
- # 7. Verify a variant you know they carry.
148
- afquery variant-info --db ./db/ --locus chr1:887801
149
- ```
150
-
151
- Re-added samples receive new sample IDs — IDs are never reused after a removal. That is
152
- expected and does not affect results.
153
-
154
- If the original VCFs are no longer available, stop after step 5. The samples are then
155
- absent from both the metadata and `AN`, which is a correct smaller cohort rather than a
156
- biased larger one. Rebuilding with `create-db` is always a valid fallback.
157
-
158
- Databases that were only ever built with `create-db`, and never updated, are unaffected.
159
-
160
- ---
161
-
162
84
  ## Compact Takes a Long Time
163
85
 
164
86
  **Symptom:** `afquery update-db --compact` runs for many minutes or hours.
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '0.4.1'
22
- __version_tuple__ = version_tuple = (0, 4, 1)
21
+ __version__ = version = '0.4.2'
22
+ __version_tuple__ = version_tuple = (0, 4, 2)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -4,6 +4,8 @@ import sys
4
4
 
5
5
  import click
6
6
 
7
+ from afquery import __version__
8
+
7
9
  from .database import Database
8
10
 
9
11
 
@@ -168,15 +170,18 @@ def _print_carriers(carriers, variant_key, fmt: str) -> None:
168
170
  click.echo(fmt_row.format(*row))
169
171
 
170
172
 
171
- @click.group()
172
- def cli():
173
- """AFQuery: bitmap-indexed allele frequency engine for local genomic cohorts.
173
+ _CLI_HELP = f"""\
174
+ AFQuery v{__version__} — bitmap-indexed allele frequency engine for local genomic cohorts.
174
175
 
175
- Enables fast AC/AN/AF queries on user-defined subcohorts (phenotype, sex,
176
- technology) without rescanning VCFs.
176
+ Enables fast AC/AN/AF queries on user-defined subcohorts (phenotype, sex,
177
+ technology) without rescanning VCFs.
178
+ """
177
179
 
178
- Commands: query, variant-info, annotate, dump, info, version, create-db, update-db, check, benchmark
179
- """
180
+
181
+ @click.group(help=_CLI_HELP)
182
+ @click.version_option(version=__version__, prog_name="afquery", message="%(prog)s %(version)s")
183
+ def cli():
184
+ pass
180
185
 
181
186
 
182
187
  @cli.command()
@@ -375,6 +375,29 @@ def test_version_set_then_show(runner, db_copy):
375
375
  assert "MYVER" in result.output
376
376
 
377
377
 
378
+ # --- afquery --version / --help ---
379
+
380
+ def test_version_flag(runner):
381
+ from afquery import __version__
382
+ result = runner.invoke(cli, ["--version"])
383
+ assert result.exit_code == 0
384
+ assert __version__ in result.output
385
+
386
+
387
+ def test_help_shows_program_name_and_version(runner):
388
+ from afquery import __version__
389
+ result = runner.invoke(cli, ["--help"])
390
+ assert result.exit_code == 0
391
+ assert f"AFQuery v{__version__}" in result.output
392
+
393
+
394
+ def test_help_lists_all_commands(runner):
395
+ result = runner.invoke(cli, ["--help"])
396
+ for cmd in ("query", "variant-info", "annotate", "dump", "info",
397
+ "version", "create-db", "update-db", "check", "benchmark"):
398
+ assert cmd in result.output
399
+
400
+
378
401
  # --- afquery check ---
379
402
 
380
403
  def test_check_ok(runner, test_db):
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes