Skip to content

feat: license.licensing implementation - #948

Open
lmco-shuynh wants to merge 11 commits into
CycloneDX:mainfrom
lmco-shuynh:feat/licensing
Open

lmco-shuynh wants to merge 11 commits into
CycloneDX:mainfrom
lmco-shuynh:feat/licensing

Conversation

@lmco-shuynh

@lmco-shuynh lmco-shuynh commented Mar 16, 2026 •

Copy link
Copy Markdown

Description

Adds license.licensing support. Adding this helps support our internal use cases for tracking vendor licensing terms for software we purchase/license.

Resolves or fixes issue: #578

AI Tool Disclosure

  • My contribution does not include any AI-generated content
  • My contribution includes AI-generated content, as disclosed below:
    • AI Tools: Windsurf
    • LLMs and versions: Claude Opus 4.6 Thinking
    • Prompts: Ex: Create unit tests to exercise the newly added licensing field in license. Update documentation to reflect newly added changes

Affirmation

@lmco-shuynh
lmco-shuynh requested a review from a team as a code owner March 16, 2026 22:59
Comment thread docs/schema-support.rst Resolved
@read-the-docs-community

read-the-docs-community Bot commented Mar 16, 2026 •

Copy link
Copy Markdown

@jkowalleck jkowalleck added enhancement New feature or request schema 1.5 labels Mar 17, 2026
Comment thread cyclonedx/model/license.py Resolved
@jkowalleck

Copy link
Copy Markdown
Member

thank you for taking care of this feature, @lmco-shuynh

please add the new capability to the existing test model in https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/tests/_data/models.py
i think get_bom_with_licenses should be the right place , similar as #947 done it

@jkowalleck

Copy link
Copy Markdown
Member

@lmco-shuynh please rebase onto latest main branch

Signed-off-by: Shaun Huynh <shaun.huynh@lmco.com>
Signed-off-by: Shaun Huynh <shaun.huynh@lmco.com>
Signed-off-by: Shaun Huynh <shaun.huynh@lmco.com>
Signed-off-by: Shaun Huynh <shaun.huynh@lmco.com>
@lmco-shuynh

lmco-shuynh commented Mar 17, 2026 •

Copy link
Copy Markdown
Author

@jkowalleck I've rebased, updated some URLs, and updated the test for get_bom_with_licenses.

Thanks for your help reviewing these changes

@lmco-shuynh
lmco-shuynh requested a review from jkowalleck April 13, 2026 20:55
@codacy-production

codacy-production Bot commented Jun 4, 2026 •

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 52 complexity · 0 duplication

Metric Results
Complexity 52
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 commented Jun 17, 2026 •

Copy link
Copy Markdown
Member

please rebase merge or onto latest main branch - and fix the conflicts..
it brings additional tests that might be needed here.



@serializable.serializable_enum
class LicenseType(str, Enum):

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.

please add tests for completeness to tests/test_enums.py

@saquibsaifee

Copy link
Copy Markdown
Contributor

@lmco-shuynh is the ready from your side?

Copy link
Copy Markdown
Member

review done by Claude Fable 5.2, prompt: "do a review, comment your findings"


Scope of this review: static review of the diff at c92e22d, cross-checked against the bundled 1.5 and 1.7 JSON schemas and the 1.7 XSD. I did not run the test suite, and the Python CI workflow has not reported for this head (only DCO, Codacy and GitGuardian have), so the tests and snapshots are unverified.

Overall: the model matches the schema. Property names, XML element names and order (altIds/altId, licensor, licensee, purchaser, purchaseOrder, licenseTypes/licenseType, lastRenewal, expiration), the enum values, and the 1.5+ view gating are all correct. licensing sits correctly between url and properties in DisjunctiveLicense. The findings below are ordered by importance.

Blocking

  1. DCO check is failing (ACTION_REQUIRED). The commits need a sign-off before this can merge.

Should fix

  1. LicenseEntity can be put into an invalid state through its setters (cyclonedx/model/license.py, organization / individual setters).
    The constructor enforces exactly one of the two, but the setters do not. LicenseEntity(organization=o).organization = None leaves both as None. That serializes to "licensor": {}, which violates the JSON schema (oneOf: required organization | required individual).
    test_set_organization_none_keeps_individual and its sibling only cover the harmless direction.
    Either raise when a setter would leave both empty, or drop the setters' implicit clearing and make the class effectively immutable.

  2. docs/schema-support.rst is inaccurate after this change.

    • DisjunctiveLicense still says "Not currently supported: properties", but properties is implemented (xml_sequence(6), views 1.5–1.7). The cell should be empty.
    • LicenseExpression is now shown with no gaps. In 1.7 the detailed expression also allows licensing and properties (JSON licenseChoice/items/oneOf/1/properties/licensing; XSD licensing element after details), and neither is modelled. Please list them as unsupported rather than leaving the cell empty.
  3. licensing on LicenseExpression (1.7) is not implemented. That is fine for this PR's scope, but [TRACKING] Complete support for CycloneDX v1.5 #578 should not be considered fully resolved for 1.7. Either add it here (the Licensing class is reusable as is) or say so in the PR description and open a follow-up.

Minor

  1. test_equal_with_licensing does not test value equality. a and b share the same Licensing instance, so the test would pass even if Licensing.__eq__ were identity-based. Build two equal instances instead.

  2. altId is xs:normalizedString in the XSD, but alt_ids has no normalization applied (compare license_identifier, which uses xml_string(NORMALIZED_STRING)). Values containing tabs or newlines would be emitted unnormalized in XML.

  3. alt_ids and license_types are SortedSets, so input order is lost and duplicates are dropped. That is consistent with the rest of the library and probably intended; I am flagging it only because altIds is a plain array in the schema.

  4. Unrelated tests were added (test_equal_with_acknowledgement, test_equal_different_acknowledgement), and a blank line after class TestModelLicense was removed. These are harmless but outside this feature's scope.

  5. Docstring schema links use the metadata_tools_oneOf_i0_components_items_licenses_… anchors. A shorter anchor such as the XML type_licensingType one, in the style used by LicenseExpressionDetails, would be more stable.

Checked and fine

  • TestEnumLicenseType covers both JSON locations: inline definitions.license.properties.licensing (1.5/1.6) and top-level definitions.licensing (1.7). The XSD licenseTypeEnum xpath is correct.
  • The enum_LicenseType snapshots for 1.4 and below correctly omit licensing, and the 1.7 XML snapshot is in schema order.
  • licensing is included in DisjunctiveLicense.__comparable_tuple, so equality, hashing and sorting take it into account.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request schema 1.5

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants