# Contributing

> Set up a development environment, run the tests, and open a pull request for the Data Contract CLI.

# Contributing

The Data Contract CLI is open source under the [MIT license](https://github.com/datacontract/datacontract-cli/blob/main/LICENSE) and contributions are welcome — a new importer or exporter, support for another data source, a bug fix, or a documentation improvement.

- **Source code**: [github.com/datacontract/datacontract-cli](https://github.com/datacontract/datacontract-cli)
- **Issues**: [github.com/datacontract/datacontract-cli/issues](https://github.com/datacontract/datacontract-cli/issues)
- **Questions and discussion**: [Community Slack](https://datacontract.com/slack)

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](https://docs.astral.sh/uv/) is the recommended toolchain.

```bash
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:

```bash
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:

```bash
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:

```bash
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

```bash
# 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:

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

Many tests use [testcontainers](https://testcontainers.com/), 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](https://docs.astral.sh/ruff/) with a 120-character line length. CI fails on unformatted code.

```bash
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](https://docusaurus.io/) project in `docs/`:

```bash
cd docs
npm install
npm start
```

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

```bash
python update_command_docs.py       # the whole Commands section, from the CLI --help output
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)
```

Everything under `docs/docs/commands/` is generated — `_category_.json` is the only hand-written file there. Prose guides belong in `docs/docs/imports`, `exports`, or `testing`, and each one links to its generated command page (and back). `tests/test_docs_commands.py` fails if either is stale.

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:

```markdown
- 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.
