hgvs-weaver-data 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.
- hgvs_weaver_data-0.1.0/.claude/rules/design-docs.md +6 -0
- hgvs_weaver_data-0.1.0/.claude/rules/python.md +6 -0
- hgvs_weaver_data-0.1.0/.claude/rules/tests.md +9 -0
- hgvs_weaver_data-0.1.0/.claude/skills/writing-design-docs/SKILL.md +55 -0
- hgvs_weaver_data-0.1.0/.gitattributes +5 -0
- hgvs_weaver_data-0.1.0/.github/workflows/lint.yml +34 -0
- hgvs_weaver_data-0.1.0/.github/workflows/release.yml +61 -0
- hgvs_weaver_data-0.1.0/.github/workflows/schema-compat.yml +49 -0
- hgvs_weaver_data-0.1.0/.github/workflows/schema-freshness.yml +38 -0
- hgvs_weaver_data-0.1.0/.github/workflows/tests.yml +23 -0
- hgvs_weaver_data-0.1.0/.gitignore +11 -0
- hgvs_weaver_data-0.1.0/.pre-commit-config.yaml +58 -0
- hgvs_weaver_data-0.1.0/.yamlfmt +10 -0
- hgvs_weaver_data-0.1.0/CLAUDE.md +95 -0
- hgvs_weaver_data-0.1.0/GLOSSARY.md +52 -0
- hgvs_weaver_data-0.1.0/LICENSE +21 -0
- hgvs_weaver_data-0.1.0/PKG-INFO +62 -0
- hgvs_weaver_data-0.1.0/README.md +45 -0
- hgvs_weaver_data-0.1.0/buf.lock +6 -0
- hgvs_weaver_data-0.1.0/buf.yaml +23 -0
- hgvs_weaver_data-0.1.0/docs/PRODUCT.md +65 -0
- hgvs_weaver_data-0.1.0/docs/design/placements.md +202 -0
- hgvs_weaver_data-0.1.0/docs/design/retired-versions.md +142 -0
- hgvs_weaver_data-0.1.0/docs/style/design-docs.md +117 -0
- hgvs_weaver_data-0.1.0/docs/style/general.md +61 -0
- hgvs_weaver_data-0.1.0/docs/style/python.md +272 -0
- hgvs_weaver_data-0.1.0/docs/style/writing-tests.md +211 -0
- hgvs_weaver_data-0.1.0/proto/weaver_data_provider/v1/bundle.proto +195 -0
- hgvs_weaver_data-0.1.0/proto/weaver_data_provider/v1/genome.proto +53 -0
- hgvs_weaver_data-0.1.0/proto/weaver_data_provider/v1/index.proto +53 -0
- hgvs_weaver_data-0.1.0/proto/weaver_data_provider/v1/store.proto +92 -0
- hgvs_weaver_data-0.1.0/pyproject.toml +86 -0
- hgvs_weaver_data-0.1.0/scripts/fetch_refseq_status.py +218 -0
- hgvs_weaver_data-0.1.0/scripts/regen.py +40 -0
- hgvs_weaver_data-0.1.0/src/buf/__init__.py +0 -0
- hgvs_weaver_data-0.1.0/src/buf/validate/__init__.py +0 -0
- hgvs_weaver_data-0.1.0/src/buf/validate/validate_pb2.py +469 -0
- hgvs_weaver_data-0.1.0/src/buf/validate/validate_pb2.pyi +654 -0
- hgvs_weaver_data-0.1.0/src/weaver_data_provider/__init__.py +10 -0
- hgvs_weaver_data-0.1.0/src/weaver_data_provider/_files.py +105 -0
- hgvs_weaver_data-0.1.0/src/weaver_data_provider/build/__init__.py +44 -0
- hgvs_weaver_data-0.1.0/src/weaver_data_provider/build/cli.py +254 -0
- hgvs_weaver_data-0.1.0/src/weaver_data_provider/build/common.py +367 -0
- hgvs_weaver_data-0.1.0/src/weaver_data_provider/build/ensembl.py +536 -0
- hgvs_weaver_data-0.1.0/src/weaver_data_provider/build/genome.py +112 -0
- hgvs_weaver_data-0.1.0/src/weaver_data_provider/build/refseq.py +841 -0
- hgvs_weaver_data-0.1.0/src/weaver_data_provider/build/store.py +255 -0
- hgvs_weaver_data-0.1.0/src/weaver_data_provider/genome.py +165 -0
- hgvs_weaver_data-0.1.0/src/weaver_data_provider/keytable.py +97 -0
- hgvs_weaver_data-0.1.0/src/weaver_data_provider/provider.py +215 -0
- hgvs_weaver_data-0.1.0/src/weaver_data_provider/py.typed +0 -0
- hgvs_weaver_data-0.1.0/src/weaver_data_provider/refget.py +40 -0
- hgvs_weaver_data-0.1.0/src/weaver_data_provider/store.py +226 -0
- hgvs_weaver_data-0.1.0/src/weaver_data_provider/testing.py +194 -0
- hgvs_weaver_data-0.1.0/src/weaver_data_provider/v1/__init__.py +0 -0
- hgvs_weaver_data-0.1.0/src/weaver_data_provider/v1/bundle_pb2.py +109 -0
- hgvs_weaver_data-0.1.0/src/weaver_data_provider/v1/bundle_pb2.pyi +204 -0
- hgvs_weaver_data-0.1.0/src/weaver_data_provider/v1/genome_pb2.py +65 -0
- hgvs_weaver_data-0.1.0/src/weaver_data_provider/v1/genome_pb2.pyi +42 -0
- hgvs_weaver_data-0.1.0/src/weaver_data_provider/v1/index_pb2.py +50 -0
- hgvs_weaver_data-0.1.0/src/weaver_data_provider/v1/index_pb2.pyi +37 -0
- hgvs_weaver_data-0.1.0/src/weaver_data_provider/v1/store_pb2.py +84 -0
- hgvs_weaver_data-0.1.0/src/weaver_data_provider/v1/store_pb2.pyi +59 -0
- hgvs_weaver_data-0.1.0/tests/test_ensembl.py +688 -0
- hgvs_weaver_data-0.1.0/tests/test_genome.py +196 -0
- hgvs_weaver_data-0.1.0/tests/test_provider.py +202 -0
- hgvs_weaver_data-0.1.0/tests/test_refseq.py +1370 -0
- hgvs_weaver_data-0.1.0/tests/test_store.py +502 -0
- hgvs_weaver_data-0.1.0/tools/check_links.py +165 -0
- hgvs_weaver_data-0.1.0/uv.lock +1094 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: writing-design-docs
|
|
3
|
+
description: "Write or substantially rewrite a design doc under `docs/design/`. The procedure: what to read before drafting, what stays in the doc versus what moves to the code, the shape to draft in, the self-read, and the checks. Use when authoring a new design doc, rewriting an existing one, splitting or folding one, or bringing a doc up to the guide."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Writing a design doc
|
|
7
|
+
|
|
8
|
+
The guidance is `docs/style/design-docs.md` — the reader, the style, where low-level detail goes, the default shape, the
|
|
9
|
+
policy. This is the procedure; it does not restate the guide.
|
|
10
|
+
|
|
11
|
+
## Read first
|
|
12
|
+
|
|
13
|
+
- The guide.
|
|
14
|
+
- What the doc's reader has already read: `docs/PRODUCT.md`, `GLOSSARY.md`.
|
|
15
|
+
- The doc as it stands, where one exists, and the Overview of each doc that will appear under `Related`.
|
|
16
|
+
- The code and contract files the doc describes — the proto, the module entry points, the tests. "The code states it" is
|
|
17
|
+
verified there before a fact is left out, never assumed.
|
|
18
|
+
|
|
19
|
+
## Separate what stays from what restates code
|
|
20
|
+
|
|
21
|
+
Stays: the decisions, the named interfaces and what each promises, the consequences, the alternatives and why each was
|
|
22
|
+
rejected, open questions.
|
|
23
|
+
|
|
24
|
+
Goes: per-field paraphrase of a proto or schema, env-var names, paths beyond an entry point, function, class and test
|
|
25
|
+
names, error strings, constants.
|
|
26
|
+
|
|
27
|
+
For each code-owned fact the doc does not carry, note where it lives — the comment on the proto field, the docstring,
|
|
28
|
+
the test — or that it has no home yet because that code does not exist on this branch. Keep the list; it is part of the
|
|
29
|
+
report. No such fact goes into an inline comment beside the implementation (`docs/style/general.md`, Comments).
|
|
30
|
+
|
|
31
|
+
## Draft
|
|
32
|
+
|
|
33
|
+
The guide's default shape, deviating where the design reads better another way. A doc covering a surface, a flow, or
|
|
34
|
+
several interfaces uses the concrete forms the guide names: a mockup of the surface, a request diagram, a plain
|
|
35
|
+
statement of what is stored where, one subsection per interface in one consistent shape.
|
|
36
|
+
|
|
37
|
+
## Re-read as the reader
|
|
38
|
+
|
|
39
|
+
Read the draft as the maintainer the guide describes — has read `PRODUCT.md` and `GLOSSARY.md`, knows nothing about the
|
|
40
|
+
area, one read on GitHub. Can they state each decision and the reason for it afterwards? Where not, fix the passage, not
|
|
41
|
+
the reader.
|
|
42
|
+
|
|
43
|
+
## Checks
|
|
44
|
+
|
|
45
|
+
- `python3 tools/check_links.py` from the repo root — it scans all tracked Markdown, so read only the lines naming the
|
|
46
|
+
doc.
|
|
47
|
+
- `pre-commit run mdformat --files <doc>`.
|
|
48
|
+
- After the push, check a mermaid block in the branch's file view on GitHub; the PR diff will not render it, so a
|
|
49
|
+
reviewer opens the file.
|
|
50
|
+
- The header line carries `**Related:**`.
|
|
51
|
+
|
|
52
|
+
## Report
|
|
53
|
+
|
|
54
|
+
Where each code-owned fact lives, calling out the ones with no home yet so the author can push them onto the code's
|
|
55
|
+
documentation surface when it lands. Any question the writing raised for the author.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Generated protobuf stubs: collapse in GitHub diffs and drop from language stats.
|
|
2
|
+
# Collapse only — GitHub still counts these lines in a PR's +/- total, as with any
|
|
3
|
+
# lockfile; to inspect one, expand it in the diff.
|
|
4
|
+
**/*_pb2.py linguist-generated=true
|
|
5
|
+
**/*_pb2.pyi linguist-generated=true
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: lint
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, ready_for_review, synchronize]
|
|
6
|
+
push:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
pre-commit:
|
|
11
|
+
# Runs every hook in .pre-commit-config.yaml — the whole static-check gate. Skips draft PRs.
|
|
12
|
+
if: github.event_name != 'pull_request' || !github.event.pull_request.draft
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v7
|
|
18
|
+
- uses: astral-sh/setup-uv@v10.2.0
|
|
19
|
+
with:
|
|
20
|
+
enable-cache: true
|
|
21
|
+
# buf on PATH for the buf-lint hook.
|
|
22
|
+
- uses: bufbuild/buf-setup-action@v1.50.0
|
|
23
|
+
with:
|
|
24
|
+
version: "1.73.0"
|
|
25
|
+
# No default token: the release lookup that resolves the download URL would go out
|
|
26
|
+
# anonymous, against a per-IP rate limit shared across the hosted runner pool.
|
|
27
|
+
github_token: ${{ github.token }}
|
|
28
|
+
# Pre-sync the env so the pyright hook's `uv run` is a no-op.
|
|
29
|
+
- run: uv sync --locked --python 3.13
|
|
30
|
+
- uses: actions/cache@v6
|
|
31
|
+
with:
|
|
32
|
+
path: ~/.cache/pre-commit
|
|
33
|
+
key: pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
|
|
34
|
+
- run: uv run pre-commit run --all-files --show-diff-on-failure
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
|
|
3
|
+
# A `v*` tag builds, tests, publishes to PyPI through the trusted publisher registered for this
|
|
4
|
+
# workflow (environment `pypi`), and creates the GitHub release with the built distributions.
|
|
5
|
+
on:
|
|
6
|
+
push:
|
|
7
|
+
tags: ["v*"]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v7
|
|
16
|
+
- uses: astral-sh/setup-uv@v10.2.0
|
|
17
|
+
with:
|
|
18
|
+
enable-cache: true
|
|
19
|
+
# The tag is the release's name; the wheel's version comes from pyproject.toml. They must agree,
|
|
20
|
+
# or PyPI shows one version and the repo another.
|
|
21
|
+
- name: Check the tag matches the package version
|
|
22
|
+
run: |
|
|
23
|
+
set -euo pipefail
|
|
24
|
+
version="$(uv version --short)"
|
|
25
|
+
if [ "v${version}" != "${GITHUB_REF_NAME}" ]; then
|
|
26
|
+
echo "::error::tag ${GITHUB_REF_NAME} does not match pyproject version ${version}"
|
|
27
|
+
exit 1
|
|
28
|
+
fi
|
|
29
|
+
- run: uv sync --locked --python 3.13
|
|
30
|
+
- run: uv run pytest
|
|
31
|
+
- run: uv build
|
|
32
|
+
- uses: actions/upload-artifact@v7
|
|
33
|
+
with:
|
|
34
|
+
name: dist
|
|
35
|
+
path: dist/
|
|
36
|
+
if-no-files-found: error
|
|
37
|
+
|
|
38
|
+
publish:
|
|
39
|
+
needs: build
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
environment:
|
|
42
|
+
name: pypi
|
|
43
|
+
url: https://pypi.org/project/hgvs-weaver-data/${{ github.ref_name }}
|
|
44
|
+
permissions:
|
|
45
|
+
# OIDC token for PyPI trusted publishing; contents for the GitHub release.
|
|
46
|
+
id-token: write
|
|
47
|
+
contents: write
|
|
48
|
+
steps:
|
|
49
|
+
- uses: actions/download-artifact@v8
|
|
50
|
+
with:
|
|
51
|
+
name: dist
|
|
52
|
+
path: dist/
|
|
53
|
+
- uses: pypa/gh-action-pypi-publish@v1.14.2
|
|
54
|
+
- name: Create the GitHub release
|
|
55
|
+
env:
|
|
56
|
+
GH_TOKEN: ${{ github.token }}
|
|
57
|
+
run: |-
|
|
58
|
+
gh release create "${GITHUB_REF_NAME}" dist/* \
|
|
59
|
+
--repo "${GITHUB_REPOSITORY}" \
|
|
60
|
+
--title "hgvs-weaver-data ${GITHUB_REF_NAME#v}" \
|
|
61
|
+
--generate-notes
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
name: schema-compat
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, ready_for_review, synchronize]
|
|
6
|
+
push:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
backward-compatible:
|
|
11
|
+
# `buf breaking` under the FILE rule set (buf.yaml): stores and genomes already written sit in
|
|
12
|
+
# other projects' buckets, so a renumber or type change of a committed field fails here.
|
|
13
|
+
# Skips draft PRs.
|
|
14
|
+
if: github.event_name != 'pull_request' || !github.event.pull_request.draft
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
permissions:
|
|
17
|
+
contents: read
|
|
18
|
+
steps:
|
|
19
|
+
# Full history: the baseline is a commit, not the checkout.
|
|
20
|
+
- uses: actions/checkout@v7
|
|
21
|
+
with:
|
|
22
|
+
fetch-depth: 0
|
|
23
|
+
- uses: bufbuild/buf-setup-action@v1.50.0
|
|
24
|
+
with:
|
|
25
|
+
version: "1.73.0"
|
|
26
|
+
# No default token: the release lookup that resolves the download URL would go out
|
|
27
|
+
# anonymous, against a per-IP rate limit shared across the hosted runner pool.
|
|
28
|
+
github_token: ${{ github.token }}
|
|
29
|
+
# Baseline = what main held before this change. For a PR that is the base branch tip; on a push
|
|
30
|
+
# it is the commit the push started from, so every commit a multi-commit push brings is compared.
|
|
31
|
+
# A push that creates the branch has no before, and falls back to the previous commit; a root
|
|
32
|
+
# commit has no baseline and is skipped.
|
|
33
|
+
- name: Resolve baseline ref
|
|
34
|
+
id: baseline
|
|
35
|
+
env:
|
|
36
|
+
BEFORE: ${{ github.event.before }}
|
|
37
|
+
run: |
|
|
38
|
+
set -euo pipefail
|
|
39
|
+
if [ "${{ github.event_name }}" = "pull_request" ]; then
|
|
40
|
+
echo "ref=origin/${{ github.base_ref }}" >> "$GITHUB_OUTPUT"
|
|
41
|
+
elif [ -n "${BEFORE:-}" ] && [ "${BEFORE}" != "0000000000000000000000000000000000000000" ]; then
|
|
42
|
+
echo "ref=${BEFORE}" >> "$GITHUB_OUTPUT"
|
|
43
|
+
elif git rev-parse --verify -q HEAD^ >/dev/null; then
|
|
44
|
+
echo "ref=HEAD^" >> "$GITHUB_OUTPUT"
|
|
45
|
+
else
|
|
46
|
+
echo "ref=" >> "$GITHUB_OUTPUT"
|
|
47
|
+
fi
|
|
48
|
+
- if: steps.baseline.outputs.ref != ''
|
|
49
|
+
run: buf breaking --against ".git#ref=${{ steps.baseline.outputs.ref }}"
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: schema-freshness
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, ready_for_review, synchronize]
|
|
6
|
+
push:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
regen-is-fresh:
|
|
11
|
+
# Skips draft PRs.
|
|
12
|
+
if: github.event_name != 'pull_request' || !github.event.pull_request.draft
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v7
|
|
18
|
+
# buf exports the protos + deps for protoc. No remote plugins — codegen is grpcio-tools' protoc.
|
|
19
|
+
- uses: bufbuild/buf-setup-action@v1.50.0
|
|
20
|
+
with:
|
|
21
|
+
version: "1.73.0"
|
|
22
|
+
# No default token: the release lookup that resolves the download URL would go out
|
|
23
|
+
# anonymous, against a per-IP rate limit shared across the hosted runner pool.
|
|
24
|
+
github_token: ${{ github.token }}
|
|
25
|
+
- uses: astral-sh/setup-uv@v10.2.0
|
|
26
|
+
with:
|
|
27
|
+
enable-cache: true
|
|
28
|
+
- run: uv run --locked --group codegen python scripts/regen.py
|
|
29
|
+
# The committed stubs must equal what regen just produced. `git add -A` stages edits, new
|
|
30
|
+
# files, and deletions; a non-empty staged diff means a .proto (or a tool) changed without
|
|
31
|
+
# regenerating.
|
|
32
|
+
- name: Fail if committed stubs are stale
|
|
33
|
+
run: |-
|
|
34
|
+
git add -A
|
|
35
|
+
if ! git diff --cached --exit-code; then
|
|
36
|
+
echo "::error::Generated stubs are stale. Run 'uv run --group codegen python scripts/regen.py' and commit the result."
|
|
37
|
+
exit 1
|
|
38
|
+
fi
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
name: tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, ready_for_review, synchronize]
|
|
6
|
+
push:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
pytest:
|
|
11
|
+
# Skips draft PRs.
|
|
12
|
+
if: github.event_name != 'pull_request' || !github.event.pull_request.draft
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v7
|
|
18
|
+
- uses: astral-sh/setup-uv@v10.2.0
|
|
19
|
+
with:
|
|
20
|
+
enable-cache: true
|
|
21
|
+
- run: uv sync --locked --python 3.13
|
|
22
|
+
# No path arg: collect the testpaths configured in pyproject.toml.
|
|
23
|
+
- run: uv run pytest
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# `pre-commit run --all-files` is the lint gate, locally and in CI. A hook added here is gated with no
|
|
2
|
+
# separate workflow edit. pytest stays a separate job (too slow for the per-commit path).
|
|
3
|
+
default_language_version:
|
|
4
|
+
python: python3.13
|
|
5
|
+
repos:
|
|
6
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
7
|
+
rev: v6.0.0
|
|
8
|
+
hooks:
|
|
9
|
+
- id: check-yaml
|
|
10
|
+
# Generated stubs are committed verbatim from protoc; a hygiene rewrite would drift them from
|
|
11
|
+
# the generator and break the freshness gate.
|
|
12
|
+
- id: end-of-file-fixer
|
|
13
|
+
exclude: '^src/(weaver_data_provider/v1|buf)/'
|
|
14
|
+
- id: trailing-whitespace
|
|
15
|
+
exclude: '^src/(weaver_data_provider/v1|buf)/'
|
|
16
|
+
- id: check-case-conflict
|
|
17
|
+
- id: check-merge-conflict
|
|
18
|
+
- id: detect-private-key
|
|
19
|
+
- id: debug-statements
|
|
20
|
+
- id: check-added-large-files
|
|
21
|
+
args: [--maxkb=1024]
|
|
22
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
23
|
+
rev: v0.15.12
|
|
24
|
+
hooks:
|
|
25
|
+
- id: ruff
|
|
26
|
+
- id: ruff-format
|
|
27
|
+
- repo: local
|
|
28
|
+
hooks:
|
|
29
|
+
# pyright needs the project deps to resolve imports, so it runs in the lint env via `uv run`.
|
|
30
|
+
# Whole-project (pass_filenames: false); fires on any staged .py.
|
|
31
|
+
- id: pyright
|
|
32
|
+
name: pyright
|
|
33
|
+
entry: uv run --group lint pyright
|
|
34
|
+
language: system
|
|
35
|
+
files: \.py$
|
|
36
|
+
pass_filenames: false
|
|
37
|
+
# buf lint: the hand-authored protos' structural and protovalidate discipline (buf.yaml).
|
|
38
|
+
# Whole-module; fires on any staged .proto. Needs buf on PATH.
|
|
39
|
+
- id: buf-lint
|
|
40
|
+
name: buf lint
|
|
41
|
+
entry: buf lint
|
|
42
|
+
language: system
|
|
43
|
+
files: \.proto$
|
|
44
|
+
pass_filenames: false
|
|
45
|
+
# Markdown formatter. CommonMark-strict, so intraword `_` (snake_case) stays literal and fenced
|
|
46
|
+
# code is untouched. gfm = tables/task-lists/autolinks; frontmatter = YAML headers. Wrap at 120.
|
|
47
|
+
- repo: https://github.com/hukkin/mdformat
|
|
48
|
+
rev: 1.0.0
|
|
49
|
+
hooks:
|
|
50
|
+
- id: mdformat
|
|
51
|
+
args: ["--wrap", "120"]
|
|
52
|
+
additional_dependencies:
|
|
53
|
+
- mdformat-gfm==1.0.0
|
|
54
|
+
- mdformat-frontmatter==2.1.2
|
|
55
|
+
- repo: https://github.com/google/yamlfmt
|
|
56
|
+
rev: v0.21.0
|
|
57
|
+
hooks:
|
|
58
|
+
- id: yamlfmt
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# YAML formatter config; the YAML analogue of ruff-format / biome.
|
|
2
|
+
# retain_line_breaks_single: yamlfmt can't selectively strip blank lines
|
|
3
|
+
# between block-sequence items, so the no-blank-line-between-steps layout in
|
|
4
|
+
# .github/workflows is kept by hand — this setting only stops yamlfmt from
|
|
5
|
+
# reintroducing or multiplying blank lines elsewhere.
|
|
6
|
+
formatter:
|
|
7
|
+
type: basic
|
|
8
|
+
retain_line_breaks_single: true
|
|
9
|
+
trim_trailing_whitespace: true
|
|
10
|
+
eof_newline: true
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# hgvs-weaver-data development notes
|
|
2
|
+
|
|
3
|
+
## Product
|
|
4
|
+
|
|
5
|
+
See [`docs/PRODUCT.md`](docs/PRODUCT.md) for the product north star — what the package is, the load-bearing principles
|
|
6
|
+
(the publisher's placement, never a derived one; the files at rest are a contract; an answer or an error, never a
|
|
7
|
+
guess), and what is out of scope. Read it before proposing designs or plans. Shared terminology lives in
|
|
8
|
+
[`GLOSSARY.md`](GLOSSARY.md).
|
|
9
|
+
|
|
10
|
+
## Working norms
|
|
11
|
+
|
|
12
|
+
Operating directives for Claude (and any agent) in this repo; they counteract default model dispositions.
|
|
13
|
+
|
|
14
|
+
- **Resist the minimal-diff reflex.** Don't reach for the smallest change that hides the symptom (special-casing,
|
|
15
|
+
papering over root causes). Aim for the correct fix at the right complexity level — not the smallest, not gold-plated.
|
|
16
|
+
- **Fail loudly and early.** Raise on a missing expected input or precondition; never fall back to a default/placeholder
|
|
17
|
+
to limp along. A placeholder is an explicit caller input, never a code default.
|
|
18
|
+
- **Never instruct around a defect — fix the defect.** Don't write prose telling readers to work around broken code —
|
|
19
|
+
"pass it as a string, the converter loses precision". Prose is untested, and callers who didn't read it stay broken.
|
|
20
|
+
- **Push back; don't just comply.** When a design, name, or approach seems worse — including a shortcut you're asked to
|
|
21
|
+
take — say so with reasoning, unprompted. The author owns the final call.
|
|
22
|
+
- **Offer better alternatives with trade-offs.** When a materially better approach than the proposed one exists, present
|
|
23
|
+
it and the trade-offs — don't just execute the ask.
|
|
24
|
+
- **Investigate before producing.** Read the code and verify constraints first. Don't treat a training-pattern
|
|
25
|
+
convention as load-bearing unchecked; don't speculate about what you can read.
|
|
26
|
+
- **Explain non-obvious changes first.** For a change whose rationale isn't self-evident, give the why before showing or
|
|
27
|
+
applying the diff.
|
|
28
|
+
- **Ask when unsure** rather than assume intent.
|
|
29
|
+
- **No intensifiers or emphasis filler.** Drop words and phrases that add emphasis but no information — "that's the
|
|
30
|
+
key", "crucially", "importantly", "the key insight", "it's worth noting". State the point plainly. Applies to all
|
|
31
|
+
prose: chat replies, PR/review comments, commit messages, and docs.
|
|
32
|
+
|
|
33
|
+
## Code style
|
|
34
|
+
|
|
35
|
+
@docs/style/general.md
|
|
36
|
+
|
|
37
|
+
Tests — what one asserts, what it may depend on, what its data may contain — follow
|
|
38
|
+
[`docs/style/writing-tests.md`](docs/style/writing-tests.md); it loads when a test file is touched.
|
|
39
|
+
|
|
40
|
+
## Schema
|
|
41
|
+
|
|
42
|
+
The protos under `proto/` are the source of truth for the files at rest; the committed Python stubs are generated. After
|
|
43
|
+
editing a proto: `buf lint`, `buf breaking --against .git#branch=main`, then
|
|
44
|
+
`uv run --group codegen python scripts/regen.py` and commit the stubs with the proto. Evolution is additive only — CI's
|
|
45
|
+
`schema-compat` job fails a renumber or type change. A change a reader cannot ignore bumps `FORMAT_VERSION`, so an old
|
|
46
|
+
reader refuses the new files rather than misreading them.
|
|
47
|
+
|
|
48
|
+
## Dependency direction
|
|
49
|
+
|
|
50
|
+
At runtime this package depends on hgvs-weaver and never the reverse ([`docs/PRODUCT.md`](docs/PRODUCT.md)). Don't
|
|
51
|
+
propose a change that makes weaver's runtime or CLI import this package; its test suite may.
|
|
52
|
+
|
|
53
|
+
## Docs
|
|
54
|
+
|
|
55
|
+
Two audiences, two registers:
|
|
56
|
+
|
|
57
|
+
- **Instruction files** are prompts and rules — `CLAUDE.md`, `.claude/rules/`, `.claude/skills/`: model-only, only what
|
|
58
|
+
changes behavior, no maintainer notes, no harness mechanics (which rules load when, where files live). A token there
|
|
59
|
+
is paid on every run that loads it; human-facing explanation belongs in `docs/` or code.
|
|
60
|
+
- **Everything under `docs/`** is written for a human first — a maintainer who has read
|
|
61
|
+
[`docs/PRODUCT.md`](docs/PRODUCT.md) and [`GLOSSARY.md`](GLOSSARY.md) but not this area, and has to get the take-aways
|
|
62
|
+
from one read on GitHub. Explain with the clarity and style of Martin Kleppmann — motivation before mechanism,
|
|
63
|
+
specifics out of the argument's way. Detail that restates code — field lists, paths, env vars, test names — stays in
|
|
64
|
+
the code and is linked, never transcribed. A model reads what a human reads. Design docs are the durable design
|
|
65
|
+
record: one living doc per area under `docs/design/`, rewritten in place; no ADRs — rationale lives in the doc,
|
|
66
|
+
chronology in git. The guide is [`docs/style/design-docs.md`](docs/style/design-docs.md); to write or rewrite one,
|
|
67
|
+
load the `writing-design-docs` skill.
|
|
68
|
+
|
|
69
|
+
## Committing
|
|
70
|
+
|
|
71
|
+
- **Stage explicit paths**, not `git add -A` / `.`; explicit staging avoids sweeping in an untracked file.
|
|
72
|
+
- **Pre-commit runs lint/format/hygiene** (`.pre-commit-config.yaml`); CI runs the same hooks plus pytest. Ensure hooks
|
|
73
|
+
are installed (`pre-commit install`) — if not, install or ask the author; never bypass with `--no-verify`.
|
|
74
|
+
- **Correct a pushed branch with a new commit on top**, not amend + force-push. PRs squash-merge, so `main` history
|
|
75
|
+
stays linear regardless and intermediate fixups vanish on merge. Reserve force-push for rebasing a branch onto `main`.
|
|
76
|
+
|
|
77
|
+
## Worktrees
|
|
78
|
+
|
|
79
|
+
Worktrees go in `.claude/worktrees/` (gitignored), never `../` siblings.
|
|
80
|
+
|
|
81
|
+
- **New branch** → the Claude Code worktree command.
|
|
82
|
+
- **Existing branch** → `git worktree add .claude/worktrees/<name> <branch>` (the command only cuts fresh branches).
|
|
83
|
+
|
|
84
|
+
## CI and review
|
|
85
|
+
|
|
86
|
+
- **Adversarially review before opening a PR.** For any change with non-trivial code or logic, run adversarial review
|
|
87
|
+
passes in subagents with fresh context — the reviewer sees only the diff, not the authoring conversation — and fix the
|
|
88
|
+
findings autonomously; repeat until a pass surfaces only diminishing findings, then open the PR. Exempt: trivial
|
|
89
|
+
changes, doc-only changes, resource/asset changes.
|
|
90
|
+
- **A PR description is written for the human reviewer**: what the change is and why, the take-aways, and where to look
|
|
91
|
+
— the altitude of a design doc's Overview, shorter. The diff carries the detail; don't narrate it. Same style:
|
|
92
|
+
[`docs/style/design-docs.md` § Style](docs/style/design-docs.md#style).
|
|
93
|
+
- **Pin third-party GitHub Actions to the latest stable release**: the moving major tag (`@v7`) where the action
|
|
94
|
+
publishes one, else the exact latest version (`@v10.2.0`). Verify against the action's releases when adding or bumping
|
|
95
|
+
one.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Glossary
|
|
2
|
+
|
|
3
|
+
Shared terms across hgvs-weaver-data docs and code.
|
|
4
|
+
|
|
5
|
+
## Reference data
|
|
6
|
+
|
|
7
|
+
- **Assembly** — one version of the reference genome, GRCh38 or GRCh37. Coordinates mean nothing without the assembly
|
|
8
|
+
they are on, so every alignment and every store names its assembly.
|
|
9
|
+
- **Annotation release** — one publication of a publisher's gene and transcript models against an assembly, named by the
|
|
10
|
+
publisher (`RS_2024_08` for RefSeq).
|
|
11
|
+
- **Transcript record** — the publisher's own sequence of a transcript (an `NM_` or `NR_` accession with its version).
|
|
12
|
+
It usually matches the genome spliced at the transcript's exons, but not always.
|
|
13
|
+
- **Alignment** (or **placement**) — where a transcript sits on one sequence of an assembly: its exons, strand, and the
|
|
14
|
+
per-exon CIGAR that says how the record and the genome differ. Published by NCBI; never derived here. A transcript can
|
|
15
|
+
have several — on X and on Y, on a chromosome and on a patch, or on each alternate locus that carries its gene.
|
|
16
|
+
- **Alternate locus** — a scaffold holding another haplotype of a region too variable for one sequence (the MHC, the KIR
|
|
17
|
+
cluster). A gene the primary assembly's haplotype lacks is placed only on alternate loci. Alternate loci are `NT_`
|
|
18
|
+
accessions, as are the unlocalized and unplaced scaffolds of the primary assembly.
|
|
19
|
+
- **Patch** — an `NW_` scaffold released between assembly versions: a fix patch corrects the primary assembly (and is
|
|
20
|
+
folded into the next major release), a novel patch adds alternate sequence.
|
|
21
|
+
- **MANE** — the NCBI/EMBL-EBI project that picks one representative transcript per protein-coding gene (MANE Select)
|
|
22
|
+
and matches it across RefSeq and Ensembl. It ranks transcripts; it does not place them.
|
|
23
|
+
- **HGNC** — the committee that assigns human gene symbols; the source of each gene's current, previous and alias
|
|
24
|
+
symbols.
|
|
25
|
+
- **refget digest** — a sequence's identity computed from its residues (sha512t24u, written `SQ.…`), so two copies of
|
|
26
|
+
the same sequence share an identifier whatever they are called.
|
|
27
|
+
|
|
28
|
+
## Project
|
|
29
|
+
|
|
30
|
+
- **Gene bundle** (or **bundle**) — the unit of storage: one gene with every transcript, protein, alignment and sequence
|
|
31
|
+
that belongs to it (`GeneBundle` in `proto/`).
|
|
32
|
+
- **Shard** — one annotation release's bundles in one bagz file, immutable once written and named for its contents.
|
|
33
|
+
- **Store** — an index over an ordered list of shards: the key tables (symbol, accession, protein, digest), the interval
|
|
34
|
+
tables (bundles by genome position), and the **manifest** that names the shards, written last.
|
|
35
|
+
- **Genome** — a derived copy of an assembly: the **blocks file**, every sequence cut into fixed-size compressed blocks,
|
|
36
|
+
and the **catalogue** of names, lengths and refget digests, written last.
|
|
37
|
+
- **Format version** — the number every manifest and catalogue carries; a reader refuses one it does not know.
|
|
38
|
+
- **Provider** — the object weaver reads through: weaver's `DataProvider` over one assembly's store and genome.
|
|
39
|
+
|
|
40
|
+
## Testing
|
|
41
|
+
|
|
42
|
+
- **Test double** — anything standing in for a production dependency in a test. The kinds below differ in fidelity and
|
|
43
|
+
in what a test can do with them
|
|
44
|
+
([`docs/style/writing-tests.md`](docs/style/writing-tests.md#test-doubles-in-order-of-fidelity)).
|
|
45
|
+
- **Fake** — a working, lightweight implementation of an interface, unsuitable for production and held to the real
|
|
46
|
+
implementation's contract.
|
|
47
|
+
- **Stub** — returns canned values to put the code under test in a state; makes no claim about being called.
|
|
48
|
+
- **Mock** — carries expectations about how it is called and fails the test when they are not met; the only double a
|
|
49
|
+
test verifies interactions on.
|
|
50
|
+
- **Change detector** — a test that pins the code's current shape rather than an invariant, so it fails on every
|
|
51
|
+
legitimate change and catches no defect.
|
|
52
|
+
- **Flaky test** — one that passes and fails on the same code; a defect to root-cause, never a reason to rerun.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Centre for Population Genomics
|
|
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.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: hgvs-weaver-data
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Reference data for the hgvs-weaver HGVS engine: a builder that cuts RefSeq and Ensembl releases into gene bundles, and the DataProvider that reads them.
|
|
5
|
+
Author-email: Tobias Sargeant <toby.sargeant@populationgenomics.org.au>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Python: >=3.12
|
|
9
|
+
Requires-Dist: bagz[gcs]>=0.3.8
|
|
10
|
+
Requires-Dist: google-cloud-storage>=2.18
|
|
11
|
+
Requires-Dist: google-crc32c>=1.5
|
|
12
|
+
Requires-Dist: hgvs-weaver>=0.7
|
|
13
|
+
Requires-Dist: protobuf<7,>=6.33.5
|
|
14
|
+
Requires-Dist: protovalidate>=1.2
|
|
15
|
+
Requires-Dist: pysam>=0.23
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
|
|
18
|
+
# hgvs-weaver-data
|
|
19
|
+
|
|
20
|
+
Reference data for [hgvs-weaver](https://github.com/populationgenomics/hgvs-weaver): a builder that turns a publisher's
|
|
21
|
+
release into a local store, and the `DataProvider` that feeds weaver from it.
|
|
22
|
+
|
|
23
|
+
An HGVS engine is only as correct as what it is told about each transcript. A RefSeq transcript's sequence is not always
|
|
24
|
+
the genome's — about one record in forty differs — and where they differ by an insertion or deletion, where the
|
|
25
|
+
difference sits is a choice. NCBI publishes its choice: the alignment of every RefSeq transcript to the assembly. The
|
|
26
|
+
builder takes that alignment exon by exon rather than deriving one, so the positions weaver computes are the ones
|
|
27
|
+
ClinVar's names and VariantValidator's projections follow.
|
|
28
|
+
|
|
29
|
+
Every placement NCBI publishes is kept — on a chromosome, an alternate locus or a patch — so a gene the primary assembly
|
|
30
|
+
lacks is served where it is. An Ensembl transcript is placed at its exons, after a check that its record is the genome
|
|
31
|
+
spliced there. [`docs/design/placements.md`](docs/design/placements.md) has the reasons. A retired RefSeq version — the
|
|
32
|
+
one an older variant name cites — is served from NCBI's historical set, stacked under the current release
|
|
33
|
+
([`docs/design/retired-versions.md`](docs/design/retired-versions.md)).
|
|
34
|
+
|
|
35
|
+
A store is one record per gene — every transcript, its protein, its alignments and the sequences they cite — in
|
|
36
|
+
[bagz](https://github.com/google-deepmind/bagz) files with sorted key and interval tables that are read into memory at
|
|
37
|
+
open. A lookup is a search over bytes in memory and one ranged read, from local disk or `gs://`.
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
weaver-data-build refseq ... # one RefSeq release's bundles, as a shard
|
|
41
|
+
weaver-data-build historical ... # NCBI's historical set of RefSeq versions, each with its Entrez status
|
|
42
|
+
# (scripts/fetch_refseq_status.py), as a shard to stack under a release's
|
|
43
|
+
weaver-data-build ensembl ... # one Ensembl release's, placed at its exons and checked against the genome
|
|
44
|
+
weaver-data-build index ... # the index and manifest over an ordered list of shards
|
|
45
|
+
weaver-data-build genome ... # the assembly, cut into compressed blocks
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The at-rest format is defined by the protos under `proto/`, and `buf breaking` gates every change: stores sit in other
|
|
49
|
+
projects' buckets, so the format only grows.
|
|
50
|
+
|
|
51
|
+
## Installing
|
|
52
|
+
|
|
53
|
+
`pip install hgvs-weaver-data`; the module is `weaver_data_provider`.
|
|
54
|
+
|
|
55
|
+
## Platforms
|
|
56
|
+
|
|
57
|
+
bagz publishes wheels for Linux x86_64 and macOS arm64; anywhere else, installing this package builds bagz from source.
|
|
58
|
+
|
|
59
|
+
## Development
|
|
60
|
+
|
|
61
|
+
`uv sync`, then `uv run pytest`. The Python stubs under `src/` are generated from `proto/` by
|
|
62
|
+
`uv run python scripts/regen.py` and committed.
|