Contributing¶
For environment setup, branching, and how to open a PR, see
CONTRIBUTING.md
in the repo root. This page covers what to do for each kind of
contribution.
Before diving in, Architecture maps every public function to the data model it takes and returns — the fastest way to see where a new piece belongs.
Ways to contribute¶
| I want to... | Go to |
|---|---|
| Report something broken | Report a bug |
| Propose something new | Request a feature |
| Fix an existing bug | Fix a bug |
Add a function to pandora/ingestion, parsing, canonicalisation, metadata, datasets, similarity, provenance, or export |
Add a function to an existing component |
Add a new annotate_*() function |
Add a new annotation |
| Write a runnable script or a narrated write-up | Write an example or recipe |
| Add a bundled fixture dataset | Build a new dataset |
| Fix or extend the docs site | Update the docs |
Report a bug¶
Open an issue with the bug template: expected vs. actual behavior, steps to reproduce, and your Pandora version/commit. Attach the mmCIF file or policy YAML if the bug depends on one.
Request a feature¶
Open an issue with the feature template: what problem it solves, and a proposed approach if you have one.
Fix a bug¶
- Find the function via Functions or
grep -rninpandora/. - Write a failing test in
tests/that reproduces it (or extend an existing one). - Fix it, then verify:
- Follow
CONTRIBUTING.mdto open the PR.
Add a function to an existing component¶
Every stage follows the same split: schema in pandora/schemas/,
logic in pandora/<package>/ (see Architecture).
- Add/extend the Pydantic model in
pandora/schemas/<module>.py, if the function needs a new typed input or output. - Add the function in
pandora/<package>/<module>.py. Keep it a pure function: take aStructure(or typed record) in, return a new one — never mutate in place. - Export it from
pandora/<package>/__init__.py's__all__if it's meant to be public API. - Docstring it: exported functions get a full description with
Args:/Returns:(andRaises:if applicable); internal helpers get one brief line. This is what powers Functions and Schemas — nothing else to do to get a new function or model documented there. - Add a test in
tests/. - If you changed which schemas reference each other, regenerate the architecture diagrams:
Add a new annotation¶
Entry-level annotations live in pandora/annotations/entry.py,
pairwise ones in pandora/annotations/pairwise.py. Both follow the
same shape as the existing annotate_*() functions: take a
Structure (or two), return an AnnotationLayer
(pandora/schemas/annotation.py). Register it in
pandora/annotations/__init__.py's __all__.
There's no formal plugin-registration system yet. If you want a plugin protocol that lets annotations be registered/discovered instead of hand-imported, that's an open, unclaimed piece of the design.
Write an example or recipe¶
Examples in examples/ are self-contained scripts that run against
the local fixtures in datasets/dev/mmcif/ — no network or external
binaries required. Follow the existing scripts' shape (see
examples/README.md), then run it to confirm it works:
A recipe is a narrated, task-oriented write-up ("how do I build a PPI dataset") built on top of an example script — PPI interface dataset is the only one so far, and a second one covering a different task (e.g. clustering by structural rather than sequence similarity, or a single-organism dataset) is a welcome contribution. To add one:
- Write the runnable script under
examples/first, if one doesn't already exist for the workflow. - Add a narrated page under
docs/recipes/that walks through it step by step — seeppi-01.md's source for the shape (prerequisites, a collapsible full script, expected output, then a per-step breakdown with links to the Usage pages each step comes from). - Register the new page in
zensical.toml'snav, under the"Recipes"list — a page not listed there builds but won't appear anywhere in the site.
Build a new dataset¶
Follow the pattern in datasets/scripts/build_dev_dataset.py: fetch
via pandora.ingestion.fetch_list_mmcif, write mmCIF files plus a
manifest.json under datasets/<name>/. Only the script and the
manifest are committed — raw mmCIF files are gitignored, so anyone can
regenerate the dataset from the script.
Update the docs¶
Preview changes locally, then verify the build is clean before
pushing (CI deploys with zensical build --clean on merge to main):
You don't need to hand-write API reference content — Functions and
Schemas are pulled straight from docstrings on every build.