Skip to main content

Analyze dependency licenses and get actionable licensing guidance for Python projects

Project description

license-audit

Analyze dependency licenses and get actionable licensing guidance for Python projects.

license-audit goes beyond simply listing dependency licenses. It tells you what license your project needs, flags incompatible combinations, and generates compliance documents.

Features

  • License Detection - Automatically detects licenses for all transitive dependencies using PEP 639 metadata, trove classifiers, and configurable overrides
  • Compatibility Analysis - Uses the OSADL compatibility matrix (123 licenses) to check whether your dependency licenses are compatible with each other
  • License Recommendations - Tells you the most permissive license your project can use given its dependencies
  • Compliance Reports - Generate Markdown, JSON, or third-party notices reports documenting your project's license posture
  • CI Integration - license-audit check provides exit codes suitable for CI/CD pipelines
  • Modern Tooling - First-class support for uv, pyproject.toml, and PEP 639

Installation

pip install license-audit

Or with uv:

uv add license-audit --dev

Usage

Analyze dependencies

By default, license-audit analyzes the current Python environment:

license-audit analyze
license-audit analyze --format json    # JSON output

Use --target to point at a specific project directory, dependency file, or virtual environment:

license-audit --target .                        # auto-detect from current dir
license-audit --target /path/to/project         # auto-detect from project dir
license-audit --target /path/to/uv.lock         # parse a specific lockfile
license-audit --target /path/to/requirements.txt  # parse a requirements file
license-audit --target /path/to/.venv           # analyze an existing venv directly

When given a dependency file or project directory, license-audit creates a temporary environment with uv, installs the dependencies, and analyzes that environment. When given a venv, it analyzes directly without creating anything.

Example output:

license-audit analyze
──────────────────── License Analysis: my-project ────────────────────

                        Dependency Licenses
┏━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━┓
┃ Package  ┃ Version ┃ License      ┃ Category   ┃ Source ┃ Parent   ┃
┡━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━┩
│ click    │ 8.1.7   │ BSD-3-Clause │ permissive │ pep639 │ (direct) │
│ pydantic │ 2.9.2   │ MIT          │ permissive │ pep639 │ (direct) │
│ rich     │ 13.9.4  │ MIT          │ permissive │ pep639 │ (direct) │
│ requests │ 2.32.3  │ Apache-2.0   │ permissive │ pep639 │ (direct) │
│ numpy    │ 1.26.4  │ BSD-3-Clause │ permissive │ pep639 │ (direct) │
│ celery   │ 5.4.0   │ BSD-3-Clause │ permissive │ pep639 │ (direct) │
└──────────┴─────────┴──────────────┴────────────┴────────┴──────────┘

Recommended Outbound Licenses (most -> least permissive):
  -> MIT
     BSD-3-Clause
     Apache-2.0
     ISC
     0BSD
  ... and 84 more

──────────────────────────── Summary ────────────────────────────
  Total dependencies: 6
  Unknown licenses:   0
  Copyleft licenses:  0
  Policy check:       PASSED

Get a license recommendation

Find out the most permissive license your project can use:

license-audit recommend
──────────────────── License Recommendation: my-project ────────────────────

Compatible licenses for your project:
  -> MIT (permissive) <- recommended
    BSD-3-Clause (permissive)
    Apache-2.0 (permissive)
    ISC (permissive)
    0BSD (permissive)

+------------------------------------------------------------------------+
|                              Guidance                                  |
| All your dependencies use permissive licenses. You are free to choose  |
| any license, including proprietary.                                    |
|                                                                        |
| Common choices: MIT (simplest), Apache-2.0 (patent grant),             |
| BSD-3-Clause (attribution).                                            |
+------------------------------------------------------------------------+

When your dependencies include copyleft licenses, the recommendation adapts:

──────────────────── License Recommendation: my-project ────────────────────

Most restrictive dependency: pandas-stubs (GPL-3.0-or-later)
  Your entire project must use a compatible copyleft license.

Compatible licenses for your project:
  -> GPL-3.0-or-later (strong-copyleft) <- recommended
    GPL-3.0-only (strong-copyleft)
    AGPL-3.0-only (network-copyleft)
    AGPL-3.0-or-later (network-copyleft)

+------------------------------------------------------------------------+
|                              Guidance                                  |
| You have strong-copyleft dependencies (e.g., GPL). Your entire project |
| must be licensed under a GPL-compatible license.                       |
|                                                                        |
| If this is not acceptable, you must find alternative dependencies with |
| permissive licenses.                                                   |
+------------------------------------------------------------------------+

CI policy check

Use license-audit check in CI pipelines for automated compliance gating:

license-audit check
license-audit check --no-fail-on-unknown     # allow unknown licenses

Override the policy level from the command line (takes precedence over pyproject.toml):

license-audit --policy permissive check          # only permissive licenses allowed
license-audit --policy weak-copyleft check       # allow LGPL, MPL, etc.
license-audit --policy strong-copyleft check     # allow GPL, etc.
license-audit --policy network-copyleft check    # allow AGPL, etc.

Exit codes:

Code Meaning
0 All dependencies pass the license policy
1 Policy violation (incompatible or denied licenses)
2 Unknown licenses detected (when fail-on-unknown = true)

GitHub Actions example

jobs:
  license-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: astral-sh/setup-uv@v5
      - run: uv sync --locked
      - run: uv run license-audit check

Generate a compliance report

Produce a Markdown or JSON compliance document:

license-audit report --output COMPLIANCE.md
license-audit report --format json --output compliance.json

The Markdown report includes a dependency table, classification breakdown, compatibility analysis, recommended licenses, and action items.

Generate a third-party notices file

Bundle all dependency license texts into a single attribution file for distribution with your software:

license-audit report --format notices --output THIRD_PARTY_NOTICES.md

The notices file includes the full license text for each dependency, pulled from PEP 639 License-File metadata or common license file names (LICENSE, COPYING, NOTICE) in each package's dist-info directory.

Update OSADL data

Refresh the bundled OSADL compatibility matrix with the latest upstream data:

license-audit refresh

Configuration

Add to your pyproject.toml:

[tool.license-audit]
fail-on-unknown = true                  # fail check when licenses can't be detected
policy = "permissive"                   # "permissive" | "weak-copyleft" | "strong-copyleft" | "network-copyleft"
allowed-licenses = ["MIT", "Apache-2.0", "BSD-3-Clause"]
denied-licenses = ["GPL-3.0-only"]
dependency-groups = ["main", "optional:api"]  # only check specific groups (default: all)

[tool.license-audit.overrides]
some-internal-package = "MIT"           # manual override for undetectable licenses
dual-licensed-pkg = "Apache-2.0 OR MIT" # SPDX expressions supported

Dependency group selectors

Selector Maps to
main [project.dependencies]
optional:<name> [project.optional-dependencies.<name>]
group:<name> [dependency-groups.<name>] (PEP 735)
dev [tool.uv.dev-dependencies]

CLI override (repeatable):

license-audit --dependency-groups main --dependency-groups group:test check

Target resolution

The --target flag determines what to analyze. The source type is inferred automatically:

Target Behavior
(none) Analyze the current Python environment directly
Project directory Auto-detect: tries uv.lock -> requirements.txt -> pyproject.toml -> .venv
uv.lock Parse lockfile, create temp environment, analyze
requirements.txt Parse requirements, create temp environment, analyze
pyproject.toml Parse [project.dependencies], optional-dependencies, dependency-groups, and [tool.uv.dev-dependencies], create temp environment, analyze
.venv directory Analyze the venv directly (no temp environment)

In all cases, [tool.license-audit] configuration is loaded from the target project's pyproject.toml.

How it works

  1. Parse - Reads your dependency specifier (uv.lock, requirements.txt, pyproject.toml, or an existing environment)
  2. Provision - Creates a temporary environment with uv and installs the dependencies (skipped when analyzing a venv or the current environment directly)
  3. Detect - Walks site-packages, reading each package's METADATA to identify licenses (PEP 639 License-Expression, License field, trove classifiers, or user overrides)
  4. Classify - Categorizes licenses as permissive, weak-copyleft, strong-copyleft, or network-copyleft using OSADL copyleft data
  5. Analyze - Checks pairwise compatibility using the OSADL matrix and identifies conflicts. For OR expressions (e.g., MIT OR GPL-2.0), picks the most permissive alternative
  6. Recommend - Determines the most permissive outbound license that satisfies all dependency constraints
  7. Report - Presents findings as terminal output, Markdown, or JSON with actionable guidance

Comparison with other tools

Capability license-audit ScanCode pip-licenses liccheck
License detection from package metadata Yes No (file-level) Yes Yes
File-level license scanning No Yes No No
Pairwise compatibility analysis (OSADL) Yes No No No
Outbound license recommendation Yes No No No
Transitive dependency tree with parents Yes N/A No No
Dual-license resolution (OR expressions) Yes (picks most permissive) N/A No No
CI policy gating with exit codes Yes Via scripting Via flags Yes
Compliance report generation Markdown, JSON, notices JSON, HTML, CSV, SPDX CSV, JSON, Markdown No
Allow/deny lists Yes Via scripting No Yes
Dependency group filtering Yes (main, dev, optional, PEP 735) N/A No No
Language support Python Any Python Python
pyproject.toml configuration Yes No No Yes
uv / PEP 639 support Yes No No No

In short: license-audit is designed for Python teams that want actionable compliance guidance, not just "what licenses do I have?" but "what can I ship, and do my dependencies conflict?" If you need file-level scanning across a polyglot codebase, ScanCode is the right tool for that job and complements license-audit well.

Limitations

  • Package-level detection only - license-audit reads the license declared in package metadata (PEP 639, License field, trove classifiers). It does not scan THIRD_PARTY_NOTICES, NOTICE, or LICENSE files inside dependencies, and cannot detect bundled/vendored code with a different license than the package declares. For file-level license scanning, see ScanCode.

  • OSADL matrix coverage - The OSADL compatibility matrix covers 123 well-known open-source licenses. Niche, custom, or proprietary licenses will produce "Unknown" compatibility verdicts. Use [tool.license-audit.overrides] to manually assign SPDX identifiers when detection fails.

  • License string normalization - PyPI packages use wildly inconsistent license strings. license-audit maps 50+ common aliases to SPDX identifiers, but uncommon or malformed strings may not be recognized and will be reported as UNKNOWN. Overrides can fill these gaps.

  • requirements.txt is flat - When analyzing a requirements.txt, only direct dependencies listed in the file are parsed. Transitive dependencies are resolved by installing into a temporary environment, but the initial spec list comes from the file as written.

  • uv.lock format stability - uv.lock does not have a formal specification. The parser supports version 1 of the lock format and will fail explicitly on unrecognized versions.

  • Environment markers - Dependency markers (platform, Python version, extras) are evaluated against the current runtime environment. Dependencies that are conditional on a different platform or Python version will not be included.

  • uv required for temp environments - When analyzing a dependency file or project directory (rather than a venv or the current environment), license-audit creates a temporary environment using uv. If uv is not installed, these targets will fail. Direct venv and current-environment analysis do not require uv.

  • No legal advice - license-audit provides informational analysis based on OSADL compatibility data. It is not a substitute for legal review. License compatibility can depend on distribution method, linking type, and jurisdiction - factors this tool does not evaluate.

License

MIT - see LICENSE for details.

This project bundles data from the OSADL Open Source License Obligations Checklists project, licensed under CC-BY-4.0. See THIRD_PARTY_NOTICES.md for full attribution.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

license_audit-0.1.1.tar.gz (133.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

license_audit-0.1.1-py3-none-any.whl (55.4 kB view details)

Uploaded Python 3

File details

Details for the file license_audit-0.1.1.tar.gz.

File metadata

  • Download URL: license_audit-0.1.1.tar.gz
  • Upload date:
  • Size: 133.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for license_audit-0.1.1.tar.gz
Algorithm Hash digest
SHA256 e7d03afabd62d5269befaa437319bfe417f3952d28f13875f98e6b47eaae41dc
MD5 64a3f33e4f7e4f176ef7ef48bd02b841
BLAKE2b-256 689ce5788addec6393607a97e532d6680a9900222f34908a3b9b2bd737a3edea

See more details on using hashes here.

Provenance

The following attestation bundles were made for license_audit-0.1.1.tar.gz:

Publisher: release.yml on dgeragh/license-audit

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file license_audit-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: license_audit-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 55.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for license_audit-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 bcd49456557fb32825261b18422ae1aefac5acc8215e56cfe497e0b1b32b8ec1
MD5 4eb71f1f67a13943290f172a30f645dd
BLAKE2b-256 283c822165bee82f16642bd0a05007a55b69979bbd8c3706e3f0e93805f614bd

See more details on using hashes here.

Provenance

The following attestation bundles were made for license_audit-0.1.1-py3-none-any.whl:

Publisher: release.yml on dgeragh/license-audit

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page