Contribution guide#
Setting up the environment#
1. Run make install-uv to install uv if not already installed
1. Run make install to install all dependencies
Code contributions#
Workflow#
Clone your fork locally with git
Make your changes
Run
make lintto run linters and formatters. This step is optional and will be executed automatically by git before you make a commit, but you may want to run it manually in order to apply fixesCommit your changes to git
Push the changes to your fork
Open a pull request. Give the pull request a descriptive title indicating what it changes. If it has a corresponding open issue, the issue number should be included in the title as well. For example a pull request that fixes issue
bug: Increased stack size making it impossible to find needle #100could be titledfix(#100): Make needles easier to find by applying fire to haystack
Tip
Pull requests and commits all need to follow the Conventional Commit format
Guidelines for writing code#
All code should be tested. This is enforced via pytest.
All code should be properly formatted. This is enforced via Ruff.
Package modules must not import
__future__.annotations. Prek checks this with an AST-based local hook.make lintapplies Ruff fixes and formatting, runs every Prek hook, checks types and slots, and audits workflows with zizmor.Prek runs only through the explicit lint command; project setup does not install Git hook shims.
Dependency resolution uses a seven-day cooldown by default, with Litestar ecosystem packages exempt so coordinated releases remain testable.
Logging#
Logger names must follow the
sqlspec.<module>hierarchy.Always obtain loggers via
sqlspec.utils.logging.get_loggerto ensure filters are attached.Use static event names in structured logs and include context fields instead of dynamic message strings.
Writing and running tests#
Put behavior shared by adapters in the contract suite. Keep vendor-only cases in that adapter's test folder. Use unit tests for code that does not need a database. The test placement guide explains where tests and fixtures belong. It also lists the checks to run.
Run the smallest relevant test file first, then run the repository gates:
make lint
make type-check
make test
make coverage
The repository-wide coverage floor is temporarily 76%. Every new commit must keep its changed code at or above 90% coverage.
Mypyc and performance gates#
SQLSpec keeps a narrow compiled surface for hot paths. If a change touches
pyproject.toml mypyc includes or excludes, tools/scripts/bench*.py,
tools/scripts/mypyc_*.py, compiled sqlspec/core or sqlspec/driver
modules, storage registry/pipeline code, data dictionary registry code, or
adapter core.py / type_converter.py files, run the focused gates below
before opening a pull request:
make install-compiled && make test
uv run python tools/scripts/mypyc_inventory.py
make install-compiled compiles the full mypyc include set (so it catches
compile errors in any compiled module), and the test suite automatically skips
the cases that cannot run against a compiled build.
For pull requests that change build hooks, wheel workflows, or compiled import boundaries, also run:
make build-performance
uv run python tools/scripts/mypyc_smoke.py
Benchmark claims need current artifacts rather than estimates. Use JSON output when capturing baselines for review:
uv run python tools/scripts/bench.py --json-output /tmp/sqlspec-bench.json
uv run python tools/scripts/bench_gate.py --json-output /tmp/sqlspec-bench-gate.json
uv run python tools/scripts/bench_subsystems.py --json-output /tmp/sqlspec-bench-subsystems.json
CI gate ownership:
Pull requests always run lint, mypy, pyright, slotscheck, docs, and the Python test matrix through
.github/workflows/ci.yml.Pull requests that touch build configuration run
.github/workflows/test-build.yml. The default pull-request path builds a subset mypyc wheel matrix; maintainers can dispatch the full architecture matrix when release confidence is needed.Releases run
.github/workflows/publish.ymlwith standard wheels, mypyc wheels, PGO on Linux and macOS, and mypyc smoke imports before publishing..github/workflows/pgo-validate.ymlis manual Linux PGO validation. It is useful for build-hook changes but is not required for every pull request.Optional services and container-backed adapter benchmarks remain manual unless their owning PR explicitly opts into those dependencies.
Project documentation#
The documentation is located in the /docs directory and is ReST and
Sphinx. If you're unfamiliar with any of those,
ReStructuredText primer and
Sphinx quickstart are recommended reads.
Running the docs locally#
You can serve the documentation with make docs-serve, or build them with make docs.
CLI demo recordings#
SQLSpec uses VHS to record terminal demos as GIF files that are embedded in the documentation.
Requirements: VHS, ffmpeg, ttyd
Installation:
go install github.com/charmbracelet/vhs@latest
Recording demos:
make docs-demos
This will process every .tape file in docs/_tapes/ and write GIF output to
docs/_static/demos/.
Creating a new tape:
Create a new
.tapefile indocs/_tapes/.Use the standard header (see existing tapes for examples). All tapes should use the
Catppuccin Mochatheme, font size 14, and 1000x600 dimensions.Use
Hide/Showcommands to hide setup steps like virtual environment activation.Include generous
Sleepdurations after commands that produce output.Run
make docs-demosto generate the GIF.Reference the GIF in your documentation with an
.. image::directive pointing to/_static/demos/<name>.gif.
Building docs with demos:
make docs-all
Creating a new release#
- Increment the version in pyproject.toml.
Note
The version should follow semantic versioning and PEP 440.
Draft a new release on GitHub
Use
vMAJOR.MINOR.PATCH(e.g.v1.2.3) as both the tag and release titleFill in the release description. You can use the "Generate release notes" function to get a draft for this
Commit your changes and push to
mainPublish the release
Go to Actions and approve the release workflow
Check that the workflow runs successfully