Developer’s guide#

This section is for working on handcalcs itself: fixing a bug, adding a feature, adding a renderer to the package, or improving these docs.

Set up in five minutes#

handcalcs uses uv for its environment.

$ git clone https://github.com/connorferster/handcalcs.git
$ cd handcalcs
$ uv sync                 # creates .venv with the package (editable) and dev tools
$ uv run pytest           # the whole suite runs in a few seconds

Build the docs:

$ uv run --extra doc sphinx-build -b html docs docs/_build/html

Open docs/_build/html/index.html.

The shape of the code#

src/handcalcs/
    __init__.py          public API: HandCalcs, handcalc, set_option, ...
    config.py            global configuration
    interfaces/          HandCalcs, @handcalc, %%render
    parsing/             source -> tree of nodes
    renderers/           tree -> output (base.py is the core)
tests/                   pytest suite; tests/golden holds golden files
docs/                    these docs (Sphinx + MyST)
scripts/                 demo and check scripts (LaTeX compile, Markdown, Excel)

Two packages do almost all the work: parsing builds the node tree, and renderers/base.py defines how a tree is rendered. Every built-in renderer is a subclass that registers handlers and rules; the renderer-building guide describes that API and applies equally to the built-in renderers.

Go deeper#

Repository layout

Every module, what it does, with links to the source.

Repository layout
The parser

From ast to handcalcs nodes: comments, commands, blocks and values.

The parser
Rendering internals

base.py walkthrough: dispatch, precedence and parentheses, calc lines.

Rendering internals
Adding a node type

Supporting new Python syntax, end to end.

Adding a node type
Tests

Suite layout, fixtures, golden files.

Tests
Documentation

Building the docs, the hc-example directive and the src role.

Documentation
Releasing

Versioning, CI and publishing to PyPI.

Releasing

Conventions#

  • Code is formatted with black; CI checks uv run black src --check.

  • Renderer branches are merged into hc2/dev during the v2 cycle; open pull requests against it.

  • Handlers and rules are module-level functions registered with decorators, named render_<type> for handlers and for what they do for rules (swap_greeks, toggle_param_line). Their docstrings say what they render and why; keep that up.