Skip to content

fix(python): normalize dependency names in PEP 621 pyproject.toml - #11050

Merged
DmitriyLewen merged 2 commits into
aquasecurity:mainfrom
sueun-dev:fix/pyproject-normalize-pep621-deps
Aug 6, 2026
Merged

fix(python): normalize dependency names in PEP 621 pyproject.toml#11050
DmitriyLewen merged 2 commits into
aquasecurity:mainfrom
sueun-dev:fix/pyproject-normalize-pep621-deps

Conversation

@sueun-dev

Copy link
Copy Markdown
Contributor

Description

PEP 621 dependencies ([project].dependencies, used by Poetry v2 and other PEP 621 backends) are stored without name normalization, while Poetry v1 dependencies ([tool.poetry.dependencies]) are normalized via python.NormalizePkgName. poetry.lock and pylock.toml store PEP 503 normalized names, so a PEP 621 dependency written in non-normalized form (canonical casing, _, or ., e.g. Flask, typing_extensions, ruamel.yaml) never matches its lock entry.

The consequence is in the poetry/pylock analyzers, which look up the direct dependencies by name (dirDeps.Contains(pkg.Name) / prodRootDeps.Contains(pkg.Name)) against the normalized lock names. A direct dependency that fails to match is reported as indirect, and since the production-dependency walk starts from the direct set, that package and its transitive subtree end up marked Dev: true. With --include-dev-deps=false they drop from the SBOM/scan, and the root -> dependency edge is lost from the graph.

Example: [project] with dependencies = ["Flask (==1.0.3)"] and a poetry.lock containing name = "flask":

before: flask  relationship=indirect  dev=true
after:  flask  relationship=direct    dev=false

The fix normalizes the PEP 621 name the same way the Poetry v1 branch already does.

How I tested

Added a TestPyProject_MainDeps case (testdata/normalize_v2.toml) with Flask, typing_extensions, and ruamel.yaml, asserting the normalized set {flask, typing-extensions, ruamel-yaml}. It fails on main (the set keeps the raw names) and passes with the change. go test ./pkg/dependency/parser/python/... ./pkg/fanal/analyzer/language/python/... stays green.

Checklist

  • I've read the guidelines for contributing to this repository.
  • I've followed the conventions in the PR title.
  • I've added tests that prove my fix is effective or that my feature works.
  • I've updated the documentation with the relevant information (if needed).
  • I've added usage information (if the PR introduces new options)

PEP 621 dependencies ([project].dependencies) were stored without name
normalization, unlike the Poetry v1 branch which normalizes via
python.NormalizePkgName. Since poetry.lock and pylock.toml store PEP 503
normalized names, a PEP 621 dependency written non-normalized (e.g. Flask,
typing_extensions, ruamel.yaml) never matches its lock entry, so it is
reported as indirect and, together with its transitive subtree, marked as a
dev dependency.

Normalize the name in the PEP 621 branch as well.
@CLAassistant

CLAassistant commented Aug 6, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

Fold the normalization fixture into `happy_v2.toml` instead of keeping a separate file.
Make the `pyproject.toml` fixtures of the poetry and pylock analyzers use non-normalized names.
Their expectations are unchanged, so both tests now fail if the normalization is dropped.

@DmitriyLewen DmitriyLewen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@DmitriyLewen
DmitriyLewen enabled auto-merge August 6, 2026 10:25
@DmitriyLewen
DmitriyLewen added this pull request to the merge queue Aug 6, 2026
Merged via the queue into aquasecurity:main with commit 0012281 Aug 6, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants