Contribution Guide#
Setting up the environment#
Run
make install-uvto install uv if not already installed.Run
make installto create the virtual environment and install all development dependencies.
Code contributions#
Workflow#
Fork the sqlspec repository.
Clone your fork locally with git.
Create a dedicated feature or bugfix branch.
Make your code changes and write tests.
Run
make lintto run code formatters, Prek hooks, type checkers, slotscheck, and workflow audits. Always run this before committing; project setup intentionally does not install Git hook shims.Commit your changes following the Conventional Commit format (e.g.
fix(#100): resolve connection pooling leakorfeat: add database adapter feature).Push the changes to your fork.
Open a pull request. Give the pull request a descriptive title indicating what it changes. Include the corresponding issue number if applicable (e.g.,
fix(#100): ...).
Tip
Pull requests and commits all need to follow the Conventional Commit format.
Guidelines for writing code#
Python Version & Typing: - Python 3.10+ baseline. - All code must be fully typed (enforced via mypy and pyright). Avoid
Anywhenever possible. - Use PEP 585 built-in collection types (dict,list,tuple,set) rather than theirtypingmodule equivalents. - Use PEP 604 union types (T | None), neverOptional[T]orUnion[T, None]. - Package modules must not importfrom __future__ import annotations. This is enforced via Ruff ruleTID251(banned API).Comments & Documentation: - Never use in-line comments in Python code. If code requires explanation, document the rationale in the class or function docstring. - Use Google-style docstrings for public classes and functions with structured
Args:,Returns:, andRaises:blocks. - Explain why something is done in a specific way, not merely what the code does.Naming Conventions: - Functions, methods, and variables:
snake_case. - Classes, exceptions, and protocols:PascalCase. - Constants and module-level singletons:SCREAMING_SNAKE_CASE.SQL Safety: - SQL queries must always use parameterized placeholders (
:paramor?). - Never use f-strings, string concatenation, or%/.format()formatting to construct SQL statements with dynamic inputs.Linting & Code Quality: - Formatting and linting are handled via Ruff and Prek. -
make lintapplies Ruff fixes and formatting, runs every Prek hook, checks types and slots, and audits workflows with zizmor. - 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#
Test Style: Use pytest function-based tests (
test_*orasync def test_*). Do not use test classes.Test Placement: - Put behavior shared by adapters in the contract suite (tests/integration/adapters/<database>/test_shared.py). - Keep vendor-only cases in that adapter's test folder (tests/integration/adapters/<database>/<driver>/). - Use unit tests (tests/unit/) for code that does not need a database (parsing, config normalization, parameter formatting). - Review the test placement guide for detailed fixture conventions.
Integration Resources: - Integration tests use
pytest-databasesfixtures to provision and manage database containers automatically.Coverage Requirements: - The repository-wide coverage floor is temporarily 76%. - Every new commit must keep changed-code coverage at or above 90%. - Detect and eliminate N+1 queries for result mapping and list operations.
Run the smallest relevant test file first, then run the repository gates:
make lint
make type-check
make test
make 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 (catching compile
errors in any compiled module), and the test suite automatically skips 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 written in
ReST and built with
Sphinx. If you're unfamiliar with either,
the ReStructuredText primer
and Sphinx quickstart are
recommended reads.
Running the docs locally#
You can serve the documentation locally with live reloading via make docs-serve, or
build the static HTML output via 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
Release process#
Releases follow Semantic Versioning and PEP 440. Release preparation is automated via the repository Makefile:
# Stable releases (patch, minor, major)
make release bump=patch
# Pre-releases
make pre-release version=0.63.0-alpha.1
See the full releases guide for detailed information on versioning schemes, pre-release cadences, deprecation policies, and the automated CI publishing pipeline.