Skip to content

Source-aware license resolution for uv projects: editables, private indexes, exact artifacts - #151

Open
joshuanapoli wants to merge 14 commits into
FHPythonUtils:masterfrom
joshuanapoli:fix/editable-local-dependencies
Open

Source-aware license resolution for uv projects: editables, private indexes, exact artifacts#151
joshuanapoli wants to merge 14 commits into
FHPythonUtils:masterfrom
joshuanapoli:fix/editable-local-dependencies

Conversation

@joshuanapoli

@joshuanapoli joshuanapoli commented Jul 30, 2026

Copy link
Copy Markdown

Purpose of This Pull Request

  • Documentation update
  • Bug fix
  • New feature
  • Other

Overview of Changes

This change gets the latest LicenseCheck to work with our monorepo. LicenseCheck was crashing because of the "pip-style editable entries".

It's also an attempt to tighten up our long list of "ignore_packages", by trying harder to understand the analyzed licenses and providing a more exact way to work around dependencies with incorrect or missing license metadata.

Audit editable and local path dependencies

LicenseCheck previously crashed when uv emitted pip-style editable entries such as:

-e ../../libs/anomaly_detection

Declares requirements-parser directly (already present transitively via depgather); uv emits pip-style requirements files whose -e <path> lines are not valid PEP 508 requirements. Passing them directly to packaging.Requirement raised InvalidRequirement.

This change:

  • Resolves active editable paths relative to the project being checked.
  • Reads each local project's name, version, author, URLs, and license from its own pyproject.toml.
  • Adds editable projects back to the audited dependency set as pinned requirements.
  • Recursively follows nested [tool.uv.sources] paths and uv workspace members.
  • Leaves configured but inactive local sources out of the audit.
  • Handles cycles, paths containing spaces, and projects whose directory and package names differ.

Audit locked versions

  • Exports an adjacent uv.lock instead of re-resolving the project.
  • Preserves exact resolved version strings for reporting and version-scoped policy rules.
  • Requests metadata for the exact package version instead of silently falling back to the latest release.
  • Honors the project's uv prerelease setting when resolution is necessary.

Support private indexes and exact artifact metadata

  • Uses uv's configured indexes and credentials to retrieve private package wheels.
  • Falls back to the exact wheel's METADATA when public PyPI is unavailable or omits usable license metadata.
  • Ignores installed metadata when the installed package version differs from the resolved version.

Partially addresses #95 and #128 by delegating package-index selection and authentication to uv.

Fixes #121 by reading the PEP 639 License-Expression field from local and downloaded artifact metadata.

Fixes #150.

Make policy evaluation safer

  • Supports package==version entries in ignore_packages and fail_packages.
  • Ensures an explicitly failed license cannot be masked by another compatible license on the same package.
  • Treats missing and unknown licenses as incompatible instead of crashing while indexing the compatibility matrix.
  • Preserves uv resolution errors for pyproject.toml rather than falling back to a less accurate parser.
  • Accepts dependencies whose custom license reference exactly matches the project's custom license reference.
  • Adds allowed_license_references / --allowed-license-references for explicitly accepting exact raw LicenseRef-* identifiers without allowing the generic proprietary-license category. Package and license deny rules retain precedence.
  • Prefers recognizable explicit legacy license metadata—SPDX expressions, exact LicenseRef-* identifiers, and conservative aliases such as Apache 2.0—over less-specific classifiers. Unrecognized legacy text continues to fall back to classifiers.
  • Safely normalizes SPDX WITH expressions without assuming every parsed expression has a .key attribute.

This precedence handles packages that publish a specific license in License alongside a generic or incorrect Trove classifier, including NVIDIA packages whose LicenseRef-NVIDIA-Proprietary or Apache 2.0 metadata was previously hidden by Other/Proprietary License.

Fixes #137.

Audit reviewed metadata overrides

Projects can supply a reviewed license when an exact artifact publishes missing, ambiguous, or incorrect metadata:

[tool.licensecheck.license_overrides]
"sample==1.2.3" = "BSD-3-Clause"
  • Override keys must use an exact name==version; ranges, wildcards, markers, extras, URLs, and unversioned names are rejected.
  • The package remains in the audit and the substituted license is evaluated by the normal package and license allow/deny rules.
  • Human-readable and structured output identify affected packages with licenseSource = "configured override".
  • A dependency update cannot silently inherit a review performed for an older artifact.

This provides a safer alternative to ignore_packages for reviewed packages with defective upstream metadata, without guessing from license text or maintaining package-specific rules in LicenseCheck.

License-matrix indexing fix

liceCompat indexed matrix.csv by list(License) position, but enum order and CSV order diverge for UPL_1/NCSA/PSFL; it now looks rows and columns up by name. Independent correctness fix, worth its own bullet.

Subprocess hardening

stdin=DEVNULL plus timeouts on both uv calls, so a private-index credential prompt can't hang a worker thread forever; artifact-fetch and resolver-fallback failures now log.

Performance

The SPDX licensing index is cached instead of rebuilt per license string, index discovery happens once per requirements file rather than once per requirement, and a duplicate uv pip install on the artifact-failure path was removed.

Testing

  • uv run pytest tests/test_packageinfo.py -q — 45 passed
  • uv run pytest -q -k 'not ansi' — 124 passed, 3 deselected
  • Ruff formatting and lint checks pass for the changed files
  • An authenticated scan of a multi-project uv monorepo, including private indexes, editable local libraries, allowed NVIDIA license references, and four exact-version metadata overrides, reports no failing packages

@joshuanapoli joshuanapoli changed the title Handle editable uv path dependencies Source-aware license resolution for uv projects: editables, private indexes, exact artifacts Aug 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant