Skip to main content

Contributing

The Data Contract CLI is open source under the MIT license and contributions are welcome — a new importer or exporter, support for another data source, a bug fix, or a documentation improvement.

For anything larger than a bug fix, open an issue first so the approach can be discussed before you write the code.

Development setup

The project targets Python 3.10–3.14 and is developed against 3.11. uv is the recommended toolchain.

gh repo clone datacontract/datacontract-cli
cd datacontract-cli

uv python pin 3.11
uv sync --all-extras --dev

Or with a plain virtual environment:

python3.11 -m venv venv
source venv/bin/activate
pip install --upgrade pip setuptools wheel
pip install -e '.[dev]'

Install the pre-commit hooks so linting and formatting run on every commit:

pre-commit install

Java (required for the PySpark tests)

Tests that use PySpark — Kafka, Delta, and DataFrame tests, and the Spark importer — need Java 21. Set JAVA_HOME before running them:

export JAVA_HOME=$(/usr/libexec/java_home -v 21)

# or with SDKMAN
source ~/.sdkman/bin/sdkman-init.sh
sdk use java 21-open

Running the tests

# The full suite (slow tests excluded by default)
uv run pytest

# In parallel
uv run pytest -n 8

# A single file or test
uv run pytest tests/test_export_sql.py
uv run pytest tests/test_export_sql.py::test_export_sql

Tests that pull large containers are marked slow and are deselected by default. Run them explicitly:

uv run pytest -m slow # only the slow tests
uv run pytest -m "slow or not slow" # everything

Many tests use testcontainers, so a running Docker daemon is needed for the data source tests.

tip

Tests describe expected behavior, not current behavior. Write the test for what the code should do; if it fails, fix the code under test rather than the test.

Linting and formatting

The project uses ruff with a 120-character line length. CI fails on unformatted code.

uv run ruff check --fix
uv run ruff format

# or run every pre-commit hook at once
pre-commit run --all-files

Documentation

The documentation site is a Docusaurus project in docs/:

cd docs
npm install
npm start

Some pages contain AUTOGENERATED blocks that must be regenerated rather than edited by hand:

python update_help.py # command help in README.md
python update_export_examples.py # command + output examples on the export pages
python update_import_examples.py # command + output examples on the import pages
python update_reference_types.py # logicalType -> native type tables on the reference pages
python lint_examples.py # validates every contract under examples/ (also runs in CI)

Every importer and exporter is listed three times — in the sidebar, in the card grid on the index page, and under Available formats: in the command reference. All three lists are alphabetical by the label that is rendered, not by file name (Import: AWS Glue sorts under A, not G). This is enforced by tests/test_docs_ordering.py.

Opening a pull request

Branch off main and make sure the checklist from the pull request template passes:

  • Tests pass (uv run pytest)
  • Code formatted (uv run ruff check --fix && uv run ruff format)
  • Docs updated (if relevant)
  • CHANGELOG.md entry added

CHANGELOG.md entries are one line each, stating what changed from a user's point of view — not how or why. Append the issue number if there is one:

- Support for the `exclusiveMinimum` logical type option (#1234)

CI runs linting, the test suite on Python 3.10–3.14, the slow tests, and an integration job that installs the built wheel and exercises the CLI end to end.