Metadata-Version: 2.5
Name: distcheck
Version: 0.1.0
Summary: Checks the licence of every distribution against a policy
Author-email: Alexander Urieles <alexander@urieles.co>
License-Expression: MIT
License-File: LICENCE
Requires-Python: >=3.12
Requires-Dist: packaging
Description-Content-Type: text/markdown

# distcheck

Checks the licence of every distribution against a policy.


## Features

- Configurable policies in `distcheck.toml` or `pyproject.toml`.
- Licence policy validation:
  - SPDX identifiers.
  - Trove classifiers.
  - Free-text licences.
- Distribution specification from `pylock.toml` lock format.
- Package exemptions with version ranges.


## Installation

### pip

distcheck is available on PyPI and can be installed with pip.

```sh
pip install distcheck
```

### uv

uv is an extremely fast Python package manager.

```sh
uv add --dev distcheck
```


## Quickstart

You want to define your policy in a `distcheck.toml` file.

```toml
allowed = ["MIT"]
```

You want to generate a distribution specification.

### pip

```sh
pip lock .
```

### uv

```sh
uv export --frozen --no-dev --format pylock.toml -o pylock.toml > /dev/null
```

You can validate your policy by using `distcheck` together with a distribution specification.

```sh
distcheck --pylock pylock.toml
```


## Configuration

All project-specific configuration can be defined in either the `pyproject.toml` file, or a file named `distcheck.toml` where options are not contained within the `tool.distcheck` table:

The `distcheck.toml` file takes precedence over the `pyproject.toml` file when both exist.


### SPDX identifiers

You can define SPDX identifier policy within the `tool.distcheck` table in the `pyproject.toml` file, or at the top level of the `distcheck.toml` file.

#### pyproject.toml

```toml
[tool.distcheck]
allowed = ["MIT", "Apache-2.0", "BSD-3-Clause"]
disallowed = ["GPL-3.0-only"]
```

#### distcheck.toml

```toml
allowed = ["MIT", "Apache-2.0", "BSD-3-Clause"]
disallowed = ["GPL-3.0-only"]
```


### Trove classifiers and free-text licence

You can define licences policy within the `tool.distcheck.licences` table in the `pyproject.toml` file, or within the `[licences]` table of the `distcheck.toml` file.


#### pyproject.toml

```toml
[tool.distcheck.licences]
allowed = ["Apache Software"]
disallowed = ["GPL v3"]
```

#### distcheck.toml

```toml
[licences]
allowed = ["Apache Software"]
disallowed = ["GPL v3"]
```


### Package exemptions

You can define a package exemption policy within the `tool.distcheck.packages` table in the `pyproject.toml` file, or within the `[packages]` table of the `distcheck.toml` file.

A package exemption names a package by its canonical name. Each value is a PEP 440 specifier saying how far the rule reaches, or `*` to reach every version.

#### pyproject.toml

```toml
[tool.distcheck.packages.allowed]
some-package = ">=2"
[tool.distcheck.packages.disallowed]
some-package = "<2"
```

#### distcheck.toml

```toml
[packages.allowed]
some-package = ">=2"
[packages.disallowed]
some-package = "<2"
```

A disallowed rule refuses a package outright, the opposite of an exemption.


## Reporting

You can generate a report by using the `--report` parameter.

```bash
distcheck --pylock pylock.toml --report licences.tsv
```

`--report` writes what the policy answered for every package, one tab-separated row of name, version, answer and licences, whether or not the check passed. It is how to see what is excused and on what grounds, which packages are still passing on a wording, and how to hand someone the licence inventory. The answer is one of:

| answer | meaning |
|---|---|
| `accepted` | an expression the top-level identifiers satisfy |
| `matched` | text a wording in `[licences]` covers, the fallback |
| `excused` | allowed by name in `[packages]`, at a version its rule reaches |
| `refused` | disallowed, by identifier, by wording, or by name |
| `unrecognised` | the policy says nothing about it either way |
| `absent` | pinned but not installed, so no licence could be read |

The exit status is zero when every pinned distribution carries a licence the policy allows and every package rule still does something.


## Licence

MIT
