Skip to content

fix: ComparablePackageURL includes name - #1022

Merged
jkowalleck merged 2 commits into
CycloneDX:mainfrom
arpitjain099:fix/comparable-purl-name
Aug 10, 2026
Merged

fix: ComparablePackageURL includes name#1022
jkowalleck merged 2 commits into
CycloneDX:mainfrom
arpitjain099:fix/comparable-purl-name

Conversation

@arpitjain099

Copy link
Copy Markdown
Contributor

Description

ComparablePackageURL built its comparison tuple from type, namespace, version, qualifiers and subpath, leaving out name. Two different packages therefore compared equal whenever everything else matched:

>>> ComparablePackageURL(PackageURL(type='pypi', name='foo', version='1.0.0')) \
...     == ComparablePackageURL(PackageURL(type='pypi', name='bar', version='1.0.0'))
True

Both collapse to ('pypi', None, '1.0.0', (), None). Since name is a required purl component and the main thing distinguishing one package from another, anything sorting components by purl treated unrelated packages as interchangeable, with their relative order left to the sort.

This adds p.name in its canonical position, between namespace and version.

Resolves or fixes issue: #1021

AI Tool Disclosure

  • My contribution does not include any AI-generated content
  • My contribution includes AI-generated content, as disclosed below:
    • AI Tools: Claude Code
    • LLMs and versions: Claude Opus 5
    • Prompts: Asked it to read cyclonedx/_internal/compare.py and check the comparison tuples against the purl spec, then to draft a regression test in the style of the existing TestComparableTuple cases. I reviewed and ran everything myself.

Affirmation

Tests

TestComparablePackageURL.test_differs_by_name fails on main, with the assertion showing the two identical tuples, and passes with the change. A second case pins that identical purls still compare equal. Full suite is 6961 tests, OK.

The comparison tuple carried type, namespace, version, qualifiers and
subpath but not name, so two purls that differ only by name compared
equal and sorted arbitrarily.

Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
@arpitjain099
arpitjain099 requested a review from a team as a code owner July 31, 2026 00:22
@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 0 complexity · 0 duplication

Metric Results
Complexity 0
Duplication 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@jkowalleck jkowalleck changed the title Include the name in ComparablePackageURL fix: ComparablePackageURL includes name Jul 31, 2026

@jkowalleck jkowalleck left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

thanks for adding a fix and the tests.

please move the tests to an own dedicated file.

Comment thread tests/test_model.py
jkowalleck
jkowalleck previously approved these changes Aug 10, 2026
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
@arpitjain099

Copy link
Copy Markdown
Contributor Author

Thanks for moving these yourself, and sorry for the delay in getting to it. Linking the regression back to #1021 in the docstring is better than what I had.

Nothing further from me. Happy to make any other changes if something is still wanted.

@jkowalleck
jkowalleck merged commit d718ac2 into CycloneDX:main Aug 10, 2026
47 checks passed
@jkowalleck

Copy link
Copy Markdown
Member

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.

[BUG] ComparablePackageURL omits the name, so purls differing only by name compare equal

2 participants