Contributing#

Development#

This package is in active development and welcomes contributions!

Feel free to bring up any questions/comments on the Zulip chat or open an issue.

All feedback is welcome and encouraged, it’s great to hear about anything that works well or could be improved.

Getting Started#

To get started locally developing with this project, fork it and clone it to your local machine.

Using the Github CLI this would be:

brew install gh
gh repo fork egraphs-good/egglog-python --clone
cd egglog-python

Then install Rust and get a Python environment set up with a compatible version. Using uv this would be:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
curl -LsSf https://astral.sh/uv/install.sh | sh

Then install the package in editable mode with the development dependencies:

uv sync --all-extras

Anytime you change the rust code, you can run uv sync --reinstall-package egglog --all-extras to force recompiling the rust code.

If you would like to download a new version of the visualizer source, run make clean; make. This will download the most recent released version from the github actions artifact in the egraph-visualizer repo. It is checked in because it’s a pain to get cargo to include only one git ignored file while ignoring the rest of the files that were ignored.

Running Tests#

To run the tests, you can use the pytest command:

uv run pytest

All code must pass ruff linters and formaters. This will be checked automatically by the pre-commit if you run pre-commit install.

To run it manually, you can use:

uv run pre-commit run --all-files ruff

If you make changes to the rust bindings, you can check that the stub files accurately reflect the rust code by running:

make stubtest

All code must all pass MyPy type checking. To run that locally use:

make mypy

Finally, to build the docs locally and test that they work, you can run:

make docs

Debugging#

To debug the Rust parts of this project, follow the PyO3 debugging guide. Debug symbols are turned on by default.

Performance#

py-spy is installed as a development dependency and can be used to profile Python code. If there is a performance sensitive piece of code, you could isolate it in a file and profile it locally with:

uv run py-spy record  --format speedscope  --  python -O tmp.py

Tracing#

pytest can also configure OpenTelemetry tracing for local debugging. For the full host-application setup and the Jaeger startup command, see Tracing. The pytest plugin configures both the Python tracer provider and egglog.bindings.setup_tracing(...) for you.

To print both Python and Rust spans to the console during a test run:

uv run pytest python/tests/test_tracing.py --benchmark-disable -q -s --otel-traces=console

Console mode is intentionally verbose. It works best for short runs or a single targeted test.

For a targeted test, pass the same flag to the test you are debugging:

uv run pytest python/tests/test_array_api.py::test_jit[lda] -vv --benchmark-disable -s --otel-traces=console

To send spans to Jaeger over OTLP/HTTP, start Jaeger as shown in Tracing, then run pytest with the Jaeger tracing mode:

uv run pytest python/tests/test_array_api.py::test_jit[lda] -vv --benchmark-disable --otel-traces=jaeger

Then open http://localhost:16686.

For a longer-running or performance-sensitive test, prefer --otel-traces=jaeger over console mode.

If you need a non-default OTLP endpoint, add --otel-otlp-endpoint=http://host:4318/v1/traces.

Making changes#

All changes that impact users should be documented in the docs/changelog.md file. Please also add tests for any new features or bug fixes.

When you are ready to submit your changes, please open a pull request. The CI will run the tests and check the code style.

Changelog Automation#

When you open a pull request, a GitHub Action automatically adds an entry to the UNRELEASED section of the changelog using your PR title and number. This ensures the changelog stays up-to-date without manual intervention.

Documentation#

We use the Diátaxis framework to organize our documentation. The “explanation” section has been renamed to “Blog” since most of the content there is more like a blog post than a reference manual. It uses the ABlog extension.

Governance#

The governance is currently informal, with Saul Shanabrook as the lead maintainer. If the project grows and there are more contributors, we will formalize the governance structure in a way to allow it to be multi-stakeholder and to spread out the power and responsibility.