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

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_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)

The Commands section under docs/docs/commands/ and the Release Notes page are generated rather than committed: npm start and npm run build rebuild them from the CLI's --help output and from CHANGELOG.md first. Nothing to regenerate by hand, and nothing to keep in sync in a pull request — _category_.json is the only file under docs/docs/commands/ that is checked in. Because the Commands section is rendered from the CLI, the docs build needs it installed (uv pip install -e '.[dev]').

Prose guides belong in docs/docs/imports, exports, or testing, and each one links to its generated command page (and back), which tests/test_docs_commands.py enforces.

Every importer and exporter is listed three times — in the sidebar, in the card grid on the index page, and in the subcommand table of the generated commands/import/index.md. 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.