diff --git a/cyclonedx_py/_internal/environment.py b/cyclonedx_py/_internal/environment.py index b5d3132c..6f39db41 100644 --- a/cyclonedx_py/_internal/environment.py +++ b/cyclonedx_py/_internal/environment.py @@ -130,7 +130,7 @@ def __call__(self, *, # type:ignore[override] rc = None else: pyproject = pyproject_load(pyproject_file) - root_c = pyproject2component(pyproject, type=mc_type) + root_c = pyproject2component(pyproject, ctype=mc_type, fpath=pyproject_file) root_c.bom_ref.value = 'root-component' root_d = tuple(pyproject2dependencies(pyproject)) rc = (root_c, root_d) diff --git a/cyclonedx_py/_internal/pipenv.py b/cyclonedx_py/_internal/pipenv.py index da1b8b99..54fbb041 100644 --- a/cyclonedx_py/_internal/pipenv.py +++ b/cyclonedx_py/_internal/pipenv.py @@ -127,7 +127,7 @@ def __call__(self, *, # type:ignore[override] if pyproject_file is None: rc = None else: - rc = pyproject_file2component(pyproject_file, type=mc_type) + rc = pyproject_file2component(pyproject_file, ctype=mc_type) rc.bom_ref.value = 'root-component' return self._make_bom(rc, diff --git a/cyclonedx_py/_internal/poetry.py b/cyclonedx_py/_internal/poetry.py index 531c55a5..6d80e578 100644 --- a/cyclonedx_py/_internal/poetry.py +++ b/cyclonedx_py/_internal/poetry.py @@ -230,7 +230,7 @@ def _make_bom(self, project: 'T_NameDict', locker: 'T_NameDict', po_cfg = project['tool']['poetry'] - bom.metadata.component = root_c = poetry2component(po_cfg, type=mc_type) + bom.metadata.component = root_c = poetry2component(po_cfg, ctype=mc_type) root_c.bom_ref.value = root_c.name root_c.properties.update( Property( diff --git a/cyclonedx_py/_internal/requirements.py b/cyclonedx_py/_internal/requirements.py index 059184ee..ee08d562 100644 --- a/cyclonedx_py/_internal/requirements.py +++ b/cyclonedx_py/_internal/requirements.py @@ -114,7 +114,7 @@ def __call__(self, *, # type:ignore[override] if pyproject_file is None: rc = None else: - rc = pyproject_file2component(pyproject_file, type=mc_type) + rc = pyproject_file2component(pyproject_file, ctype=mc_type) rc.bom_ref.value = 'root-component' if requirements_file == '-': diff --git a/cyclonedx_py/_internal/utils/packaging.py b/cyclonedx_py/_internal/utils/packaging.py index cda0ef61..97106916 100644 --- a/cyclonedx_py/_internal/utils/packaging.py +++ b/cyclonedx_py/_internal/utils/packaging.py @@ -20,7 +20,8 @@ from cyclonedx.exception.model import InvalidUriException from cyclonedx.factory.license import LicenseFactory -from cyclonedx.model import ExternalReference, ExternalReferenceType, XsUri +from cyclonedx.model import AttachedText, ExternalReference, ExternalReferenceType, XsUri +from cyclonedx.model.license import DisjunctiveLicense from .cdx import url_label_to_ert from .pep621 import classifiers2licenses @@ -42,9 +43,15 @@ def metadata2licenses(metadata: 'PackageMetadata') -> Generator['License', None, # see https://packaging.python.org/en/latest/specifications/core-metadata/#classifier-multiple-use classifiers: List[str] = metadata.get_all('Classifier') # type:ignore[assignment] yield from classifiers2licenses(classifiers, lfac) - if 'License' in metadata: + if 'License' in metadata and len(mlicense := metadata['License']) > 0: # see https://packaging.python.org/en/latest/specifications/core-metadata/#license - yield lfac.make_from_string(metadata['License']) + license = lfac.make_from_string(mlicense) + if isinstance(license, DisjunctiveLicense) and license.id is None: + # per spec, `License` is either a SPDX ID/Expression, or a license text(not name!) + yield DisjunctiveLicense(name=f"declared license of '{metadata['Name']}'", + text=AttachedText(content=mlicense)) + else: + yield license def metadata2extrefs(metadata: 'PackageMetadata') -> Generator['ExternalReference', None, None]: diff --git a/cyclonedx_py/_internal/utils/pep621.py b/cyclonedx_py/_internal/utils/pep621.py index a449c2e4..838fd956 100644 --- a/cyclonedx_py/_internal/utils/pep621.py +++ b/cyclonedx_py/_internal/utils/pep621.py @@ -15,7 +15,6 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright (c) OWASP Foundation. All Rights Reserved. - """ Functionality related to PEP 621. @@ -23,13 +22,16 @@ See https://peps.python.org/pep-0621/ """ +from base64 import b64encode from itertools import chain +from os.path import dirname, join from typing import TYPE_CHECKING, Any, Dict, Generator, Iterable, Iterator from cyclonedx.exception.model import InvalidUriException from cyclonedx.factory.license import LicenseFactory -from cyclonedx.model import ExternalReference, XsUri +from cyclonedx.model import AttachedText, Encoding, ExternalReference, XsUri from cyclonedx.model.component import Component +from cyclonedx.model.license import DisjunctiveLicense from packaging.requirements import Requirement from .cdx import licenses_fixup, url_label_to_ert @@ -50,18 +52,37 @@ def classifiers2licenses(classifiers: Iterable[str], lfac: 'LicenseFactory') -> classifiers))) -def project2licenses(project: Dict[str, Any], lfac: 'LicenseFactory') -> Generator['License', None, None]: - if 'classifiers' in project: +def project2licenses(project: Dict[str, Any], lfac: 'LicenseFactory', *, + fpath: str) -> Generator['License', None, None]: + if classifiers := project.get('classifiers'): # https://packaging.python.org/en/latest/specifications/pyproject-toml/#classifiers # https://peps.python.org/pep-0621/#classifiers # https://packaging.python.org/en/latest/specifications/core-metadata/#classifier-multiple-use - yield from classifiers2licenses(project['classifiers'], lfac) - license = project.get('license') - # https://packaging.python.org/en/latest/specifications/pyproject-toml/#license - # https://peps.python.org/pep-0621/#license - # https://packaging.python.org/en/latest/specifications/core-metadata/#license - if isinstance(license, dict) and 'text' in license: - yield lfac.make_from_string(license['text']) + yield from classifiers2licenses(classifiers, lfac) + if plicense := project.get('license'): + # https://packaging.python.org/en/latest/specifications/pyproject-toml/#license + # https://peps.python.org/pep-0621/#license + # https://packaging.python.org/en/latest/specifications/core-metadata/#license + if 'file' in plicense and 'text' in plicense: + # per spec: + # > These keys are mutually exclusive, so a tool MUST raise an error if the metadata specifies both keys. + raise ValueError('`license.file` and `license.text` are mutually exclusive,') + if 'file' in plicense: + # per spec: + # > [...] a string value that is a relative file path [...]. + # > Tools MUST assume the file’s encoding is UTF-8. + with open(join(dirname(fpath), plicense['file']), 'rb') as plicense_fileh: + yield DisjunctiveLicense(name=f"declared license of '{project['name']}'", + text=AttachedText(encoding=Encoding.BASE_64, + content=b64encode(plicense_fileh.read()).decode())) + elif len(plicense_text := plicense.get('text', '')) > 0: + license = lfac.make_from_string(plicense_text) + if isinstance(license, DisjunctiveLicense) and license.id is None: + # per spec, `License` is either a SPDX ID/Expression, or a license text(not name!) + yield DisjunctiveLicense(name=f"declared license of '{project['name']}'", + text=AttachedText(content=plicense_text)) + else: + yield license def project2extrefs(project: Dict[str, Any]) -> Generator['ExternalReference', None, None]: @@ -77,14 +98,14 @@ def project2extrefs(project: Dict[str, Any]) -> Generator['ExternalReference', N def project2component(project: Dict[str, Any], *, - type: 'ComponentType') -> 'Component': + ctype: 'ComponentType', fpath: str) -> 'Component': dynamic = project.get('dynamic', ()) return Component( - type=type, + type=ctype, name=project['name'], version=project.get('version', None) if 'version' not in dynamic else None, description=project.get('description', None) if 'description' not in dynamic else None, - licenses=licenses_fixup(project2licenses(project, LicenseFactory())), + licenses=licenses_fixup(project2licenses(project, LicenseFactory(), fpath=fpath)), external_references=project2extrefs(project), # TODO add more properties according to spec ) diff --git a/cyclonedx_py/_internal/utils/poetry.py b/cyclonedx_py/_internal/utils/poetry.py index 2427b83d..15f9b769 100644 --- a/cyclonedx_py/_internal/utils/poetry.py +++ b/cyclonedx_py/_internal/utils/poetry.py @@ -61,17 +61,18 @@ def poetry2extrefs(poetry: Dict[str, Any]) -> Generator['ExternalReference', Non pass -def poetry2component(poetry: Dict[str, Any], *, type: 'ComponentType') -> 'Component': +def poetry2component(poetry: Dict[str, Any], *, ctype: 'ComponentType') -> 'Component': licenses: List['License'] = [] lfac = LicenseFactory() if 'classifiers' in poetry: licenses.extend(classifiers2licenses(poetry['classifiers'], lfac)) if 'license' in poetry: + # per spec(https://python-poetry.org/docs/pyproject#license): + # the `license` is intended to be the name of a license, not the license text itself. licenses.append(lfac.make_from_string(poetry['license'])) - del lfac return Component( - type=type, + type=ctype, name=poetry['name'], version=poetry.get('version'), description=poetry.get('description'), diff --git a/cyclonedx_py/_internal/utils/pyproject.py b/cyclonedx_py/_internal/utils/pyproject.py index f8028aac..5719936f 100644 --- a/cyclonedx_py/_internal/utils/pyproject.py +++ b/cyclonedx_py/_internal/utils/pyproject.py @@ -14,12 +14,12 @@ def pyproject2component(data: Dict[str, Any], *, - type: 'ComponentType') -> 'Component': + ctype: 'ComponentType', fpath: str) -> 'Component': tool = data.get('tool', {}) - if 'poetry' in tool: - return poetry2component(tool['poetry'], type=type) - if 'project' in data: - return project2component(data['project'], type=type) + if poetry := tool.get('poetry'): + return poetry2component(poetry, ctype=ctype) + if project := data.get('project'): + return project2component(project, ctype=ctype, fpath=fpath) raise ValueError('Unable to build component from pyproject') @@ -33,10 +33,10 @@ def pyproject_load(pyproject_file: str) -> Dict[str, Any]: def pyproject_file2component(pyproject_file: str, *, - type: 'ComponentType') -> 'Component': + ctype: 'ComponentType') -> 'Component': return pyproject2component( pyproject_load(pyproject_file), - type=type + ctype=ctype, fpath=pyproject_file ) diff --git a/tests/_data/infiles/.gitattributes b/tests/_data/infiles/.gitattributes index b1ce527a..f83b23c8 100644 --- a/tests/_data/infiles/.gitattributes +++ b/tests/_data/infiles/.gitattributes @@ -1,3 +1,2 @@ *.bin binary *.txt.bin binary diff=text - diff --git a/tests/_data/infiles/_helpers/local_pckages/a/README.md b/tests/_data/infiles/_helpers/local_pckages/a/README.md index 19e11b7d..f091e5f6 100644 --- a/tests/_data/infiles/_helpers/local_pckages/a/README.md +++ b/tests/_data/infiles/_helpers/local_pckages/a/README.md @@ -1 +1,4 @@ -build via `python -m build` +build via : +```shell +python -m build +``` diff --git a/tests/_data/infiles/_helpers/local_pckages/a/dist/package-a-23.42.tar.gz b/tests/_data/infiles/_helpers/local_pckages/a/dist/package-a-23.42.tar.gz index 4bc8f095..62bf1071 100644 Binary files a/tests/_data/infiles/_helpers/local_pckages/a/dist/package-a-23.42.tar.gz and b/tests/_data/infiles/_helpers/local_pckages/a/dist/package-a-23.42.tar.gz differ diff --git a/tests/_data/infiles/_helpers/local_pckages/a/dist/package_a-23.42-py3-none-any.whl b/tests/_data/infiles/_helpers/local_pckages/a/dist/package_a-23.42-py3-none-any.whl index b546c551..33fc3a04 100644 Binary files a/tests/_data/infiles/_helpers/local_pckages/a/dist/package_a-23.42-py3-none-any.whl and b/tests/_data/infiles/_helpers/local_pckages/a/dist/package_a-23.42-py3-none-any.whl differ diff --git a/tests/_data/infiles/_helpers/local_pckages/a/pyproject.toml b/tests/_data/infiles/_helpers/local_pckages/a/pyproject.toml index c9f2cc3b..f055e487 100644 --- a/tests/_data/infiles/_helpers/local_pckages/a/pyproject.toml +++ b/tests/_data/infiles/_helpers/local_pckages/a/pyproject.toml @@ -2,7 +2,7 @@ name = "package-a" version = "23.42" description = "some package A" -license = {text = "Apache-2.0"} +license = { text = "some license text" } # intentional not a SPDX ID/Expression authors = [] requires-python = ">=3.8" diff --git a/tests/_data/infiles/_helpers/local_pckages/b/README.md b/tests/_data/infiles/_helpers/local_pckages/b/README.md index 19e11b7d..93a53cc1 100644 --- a/tests/_data/infiles/_helpers/local_pckages/b/README.md +++ b/tests/_data/infiles/_helpers/local_pckages/b/README.md @@ -1 +1,4 @@ -build via `python -m build` +build via +```shell +python -m build +``` diff --git a/tests/_data/infiles/_helpers/local_pckages/b/dist/package-b-23.42.tar.gz b/tests/_data/infiles/_helpers/local_pckages/b/dist/package-b-23.42.tar.gz index e5e8b0ef..ae3e9e05 100644 Binary files a/tests/_data/infiles/_helpers/local_pckages/b/dist/package-b-23.42.tar.gz and b/tests/_data/infiles/_helpers/local_pckages/b/dist/package-b-23.42.tar.gz differ diff --git a/tests/_data/infiles/_helpers/local_pckages/b/dist/package_b-23.42-py3-none-any.whl b/tests/_data/infiles/_helpers/local_pckages/b/dist/package_b-23.42-py3-none-any.whl index 2ab38d98..86ff81d5 100644 Binary files a/tests/_data/infiles/_helpers/local_pckages/b/dist/package_b-23.42-py3-none-any.whl and b/tests/_data/infiles/_helpers/local_pckages/b/dist/package_b-23.42-py3-none-any.whl differ diff --git a/tests/_data/infiles/_helpers/local_pckages/b/pyproject.toml b/tests/_data/infiles/_helpers/local_pckages/b/pyproject.toml index fdc0c21b..4cac7ff2 100644 --- a/tests/_data/infiles/_helpers/local_pckages/b/pyproject.toml +++ b/tests/_data/infiles/_helpers/local_pckages/b/pyproject.toml @@ -2,9 +2,12 @@ name = "package-b" version = "23.42" description = "some package B" -license = {text = "Apache-2.0"} +license = { text = "Apache-2.0" } # intentional same as a classifier authors = [] requires-python = ">=3.8" +classifiers = [ + "License :: OSI Approved :: Apache Software License" +] [tool.setuptools] py-modules = ["module_b"] diff --git a/tests/_data/infiles/_helpers/local_pckages/c/README.md b/tests/_data/infiles/_helpers/local_pckages/c/README.md index 19e11b7d..93a53cc1 100644 --- a/tests/_data/infiles/_helpers/local_pckages/c/README.md +++ b/tests/_data/infiles/_helpers/local_pckages/c/README.md @@ -1 +1,4 @@ -build via `python -m build` +build via +```shell +python -m build +``` diff --git a/tests/_data/infiles/_helpers/local_pckages/c/dist/package-c-23.42.tar.gz b/tests/_data/infiles/_helpers/local_pckages/c/dist/package-c-23.42.tar.gz index ee6890ed..5a7057aa 100644 Binary files a/tests/_data/infiles/_helpers/local_pckages/c/dist/package-c-23.42.tar.gz and b/tests/_data/infiles/_helpers/local_pckages/c/dist/package-c-23.42.tar.gz differ diff --git a/tests/_data/infiles/_helpers/local_pckages/c/dist/package_c-23.42-py3-none-any.whl b/tests/_data/infiles/_helpers/local_pckages/c/dist/package_c-23.42-py3-none-any.whl index 1d9fd7c1..feeeb0a4 100644 Binary files a/tests/_data/infiles/_helpers/local_pckages/c/dist/package_c-23.42-py3-none-any.whl and b/tests/_data/infiles/_helpers/local_pckages/c/dist/package_c-23.42-py3-none-any.whl differ diff --git a/tests/_data/infiles/_helpers/local_pckages/c/module_c.py b/tests/_data/infiles/_helpers/local_pckages/c/module_c.py index e23e0482..8cc519ad 100644 --- a/tests/_data/infiles/_helpers/local_pckages/c/module_c.py +++ b/tests/_data/infiles/_helpers/local_pckages/c/module_c.py @@ -15,5 +15,5 @@ """ -module B +module C """ diff --git a/tests/_data/infiles/_helpers/local_pckages/c/pyproject.toml b/tests/_data/infiles/_helpers/local_pckages/c/pyproject.toml index ee21be96..7968205c 100644 --- a/tests/_data/infiles/_helpers/local_pckages/c/pyproject.toml +++ b/tests/_data/infiles/_helpers/local_pckages/c/pyproject.toml @@ -2,9 +2,13 @@ name = "package-c" version = "23.42" description = "some package C" -license = {text = "Apache-2.0"} +license = { text = "Apache-2.0 OR MIT" } # intentional a SPDX Expression authors = [] requires-python = ">=3.8" +classifiers = [ + "License :: OSI Approved :: Apache Software License", + "License :: OSI Approved :: MIT License" +] [tool.setuptools] py-modules = ["module_c"] diff --git a/tests/_data/infiles/environment/with-license-file/init.py b/tests/_data/infiles/environment/with-license-file/init.py new file mode 100644 index 00000000..38a6cfcb --- /dev/null +++ b/tests/_data/infiles/environment/with-license-file/init.py @@ -0,0 +1,24 @@ +""" +initialize this testbed. +""" + +from os import name as os_name +from os.path import dirname, join +from venv import EnvBuilder + +__all__ = ['main'] + +this_dir = dirname(__file__) +env_dir = join(this_dir, '.venv') + + +def main() -> None: + EnvBuilder( + system_site_packages=False, + symlinks=os_name != 'nt', + with_pip=False, + ).create(env_dir) + + +if __name__ == '__main__': + main() diff --git a/tests/_data/infiles/environment/with-license-file/pyproject.toml b/tests/_data/infiles/environment/with-license-file/pyproject.toml new file mode 100644 index 00000000..427b17b4 --- /dev/null +++ b/tests/_data/infiles/environment/with-license-file/pyproject.toml @@ -0,0 +1,7 @@ +[project] +# https://packaging.python.org/en/latest/specifications/declaring-project-metadata/#declaring-project-metadata +name = "with-license-file" +version = "0.1.0" +description = "with licenses from file, instead of SPDX ID/Expression" +# see https://packaging.python.org/en/latest/specifications/pyproject-toml/#license +license = { file = "testing/someLicenseFile.txt.bin" } diff --git a/tests/_data/infiles/environment/with-license-file/testing/someLicenseFile.txt.bin b/tests/_data/infiles/environment/with-license-file/testing/someLicenseFile.txt.bin new file mode 100644 index 00000000..1c0bf5b9 --- /dev/null +++ b/tests/_data/infiles/environment/with-license-file/testing/someLicenseFile.txt.bin @@ -0,0 +1,2 @@ +This is the license text of this component. +It is expected to be available in a SBOM. diff --git a/tests/_data/infiles/environment/with-license-text/init.py b/tests/_data/infiles/environment/with-license-text/init.py new file mode 100644 index 00000000..9998905e --- /dev/null +++ b/tests/_data/infiles/environment/with-license-text/init.py @@ -0,0 +1,57 @@ +""" +initialize this testbed. +""" + +from os import name as os_name +from os.path import abspath, dirname, join +from subprocess import CompletedProcess, run # nosec:B404 +from sys import executable +from typing import Any +from venv import EnvBuilder + +__all__ = ['main'] + +this_dir = dirname(__file__) +env_dir = join(this_dir, '.venv') +constraint_file = join(this_dir, 'pinning.txt') + +localpackages_dir = abspath(join(dirname(__file__), '..', '..', '_helpers', 'local_pckages')) + + +def pip_run(*args: str, **kwargs: Any) -> CompletedProcess: + # pip is not API, but a CLI -- call it like that! + call = ( + executable, '-m', 'pip', + '--python', env_dir, + *args + ) + print('+ ', *call) + res = run(call, **kwargs, cwd=this_dir, shell=False) # nosec:B603 + if res.returncode != 0: + raise RuntimeError('process failed') + return res + + +def pip_install(*args: str) -> None: + pip_run( + 'install', '--require-virtualenv', '--no-input', '--progress-bar=off', '--no-color', + *args + ) + + +def main() -> None: + EnvBuilder( + system_site_packages=False, + symlinks=os_name != 'nt', + with_pip=False, + ).create(env_dir) + + pip_install( + join(localpackages_dir, 'a', 'dist', 'package_a-23.42-py3-none-any.whl'), + join(localpackages_dir, 'b', 'dist', 'package_b-23.42-py3-none-any.whl'), + join(localpackages_dir, 'c', 'dist', 'package_c-23.42-py3-none-any.whl'), + ) + + +if __name__ == '__main__': + main() diff --git a/tests/_data/infiles/environment/with-license-text/pyproject.toml b/tests/_data/infiles/environment/with-license-text/pyproject.toml new file mode 100644 index 00000000..14b0c56a --- /dev/null +++ b/tests/_data/infiles/environment/with-license-text/pyproject.toml @@ -0,0 +1,7 @@ +[project] +# https://packaging.python.org/en/latest/specifications/declaring-project-metadata/#declaring-project-metadata +name = "with-license-text" +version = "0.1.0" +description = "with licenses as text, instead of SPDX ID/Expression" +# see https://packaging.python.org/en/latest/specifications/pyproject-toml/#license +license = { text = "This is the license text of this component.\nIt is expected to be available in a SBOM." } diff --git a/tests/_data/snapshots/environment/plain_local_1.1.xml.bin b/tests/_data/snapshots/environment/plain_local_1.1.xml.bin index 74e71ad1..1388cf70 100644 --- a/tests/_data/snapshots/environment/plain_local_1.1.xml.bin +++ b/tests/_data/snapshots/environment/plain_local_1.1.xml.bin @@ -7,7 +7,8 @@ some package A - Apache-2.0 + declared license of 'package-a' + some license text @@ -38,9 +39,7 @@ 23.42 some package C - - Apache-2.0 - + Apache-2.0 OR MIT diff --git a/tests/_data/snapshots/environment/plain_local_1.2.json.bin b/tests/_data/snapshots/environment/plain_local_1.2.json.bin index 83c6d8b0..f1b72c5a 100644 --- a/tests/_data/snapshots/environment/plain_local_1.2.json.bin +++ b/tests/_data/snapshots/environment/plain_local_1.2.json.bin @@ -13,7 +13,11 @@ "licenses": [ { "license": { - "id": "Apache-2.0" + "name": "declared license of 'package-a'", + "text": { + "content": "some license text", + "contentType": "text/plain" + } } } ], @@ -54,9 +58,7 @@ ], "licenses": [ { - "license": { - "id": "Apache-2.0" - } + "expression": "Apache-2.0 OR MIT" } ], "name": "package-c", diff --git a/tests/_data/snapshots/environment/plain_local_1.2.xml.bin b/tests/_data/snapshots/environment/plain_local_1.2.xml.bin index 9bd185ef..679e1774 100644 --- a/tests/_data/snapshots/environment/plain_local_1.2.xml.bin +++ b/tests/_data/snapshots/environment/plain_local_1.2.xml.bin @@ -26,7 +26,8 @@ some package A - Apache-2.0 + declared license of 'package-a' + some license text @@ -57,9 +58,7 @@ 23.42 some package C - - Apache-2.0 - + Apache-2.0 OR MIT diff --git a/tests/_data/snapshots/environment/plain_local_1.3.json.bin b/tests/_data/snapshots/environment/plain_local_1.3.json.bin index 3e09434a..b387890d 100644 --- a/tests/_data/snapshots/environment/plain_local_1.3.json.bin +++ b/tests/_data/snapshots/environment/plain_local_1.3.json.bin @@ -9,7 +9,7 @@ "hashes": [ { "alg": "SHA-256", - "content": "4f37ac4a44c1dcce7f3d6203d45e9d1945a28f69fbfb44f418c44ea73c77de86" + "content": "5c8da28603857d4073c67e751ba3cd526a7ef414135faecfec164e7d01be24be" } ], "type": "distribution", @@ -19,7 +19,11 @@ "licenses": [ { "license": { - "id": "Apache-2.0" + "name": "declared license of 'package-a'", + "text": { + "content": "some license text", + "contentType": "text/plain" + } } } ], @@ -36,7 +40,7 @@ "hashes": [ { "alg": "SHA-256", - "content": "33d37cf528bc0b20ec8ffd9fa21170e7caadb1b9f15eb559d1937fa4c82d3d40" + "content": "20e983935a800046222a02674ed37baf3e7a4ef7cd40e6033d9c0efaeb73206f" } ], "type": "distribution", @@ -66,9 +70,7 @@ ], "licenses": [ { - "license": { - "id": "Apache-2.0" - } + "expression": "Apache-2.0 OR MIT" } ], "name": "package-c", diff --git a/tests/_data/snapshots/environment/plain_local_1.3.xml.bin b/tests/_data/snapshots/environment/plain_local_1.3.xml.bin index 9c663c20..99867867 100644 --- a/tests/_data/snapshots/environment/plain_local_1.3.xml.bin +++ b/tests/_data/snapshots/environment/plain_local_1.3.xml.bin @@ -29,7 +29,8 @@ some package A - Apache-2.0 + declared license of 'package-a' + some license text @@ -37,7 +38,7 @@ file://.../tests/_data/infiles/_helpers/local_pckages/a/dist/package_a-23.42-py3-none-any.whl PackageSource: Archive - 4f37ac4a44c1dcce7f3d6203d45e9d1945a28f69fbfb44f418c44ea73c77de86 + 5c8da28603857d4073c67e751ba3cd526a7ef414135faecfec164e7d01be24be @@ -56,7 +57,7 @@ file://.../tests/_data/infiles/_helpers/local_pckages/b/dist/package-b-23.42.tar.gz PackageSource: Archive - 33d37cf528bc0b20ec8ffd9fa21170e7caadb1b9f15eb559d1937fa4c82d3d40 + 20e983935a800046222a02674ed37baf3e7a4ef7cd40e6033d9c0efaeb73206f @@ -66,9 +67,7 @@ 23.42 some package C - - Apache-2.0 - + Apache-2.0 OR MIT diff --git a/tests/_data/snapshots/environment/plain_local_1.4.json.bin b/tests/_data/snapshots/environment/plain_local_1.4.json.bin index e6298492..6bdf4c88 100644 --- a/tests/_data/snapshots/environment/plain_local_1.4.json.bin +++ b/tests/_data/snapshots/environment/plain_local_1.4.json.bin @@ -9,7 +9,7 @@ "hashes": [ { "alg": "SHA-256", - "content": "4f37ac4a44c1dcce7f3d6203d45e9d1945a28f69fbfb44f418c44ea73c77de86" + "content": "5c8da28603857d4073c67e751ba3cd526a7ef414135faecfec164e7d01be24be" } ], "type": "distribution", @@ -19,7 +19,11 @@ "licenses": [ { "license": { - "id": "Apache-2.0" + "name": "declared license of 'package-a'", + "text": { + "content": "some license text", + "contentType": "text/plain" + } } } ], @@ -36,7 +40,7 @@ "hashes": [ { "alg": "SHA-256", - "content": "33d37cf528bc0b20ec8ffd9fa21170e7caadb1b9f15eb559d1937fa4c82d3d40" + "content": "20e983935a800046222a02674ed37baf3e7a4ef7cd40e6033d9c0efaeb73206f" } ], "type": "distribution", @@ -66,9 +70,7 @@ ], "licenses": [ { - "license": { - "id": "Apache-2.0" - } + "expression": "Apache-2.0 OR MIT" } ], "name": "package-c", diff --git a/tests/_data/snapshots/environment/plain_local_1.4.xml.bin b/tests/_data/snapshots/environment/plain_local_1.4.xml.bin index 4abed8df..22337ef7 100644 --- a/tests/_data/snapshots/environment/plain_local_1.4.xml.bin +++ b/tests/_data/snapshots/environment/plain_local_1.4.xml.bin @@ -56,7 +56,8 @@ some package A - Apache-2.0 + declared license of 'package-a' + some license text @@ -64,7 +65,7 @@ file://.../tests/_data/infiles/_helpers/local_pckages/a/dist/package_a-23.42-py3-none-any.whl PackageSource: Archive - 4f37ac4a44c1dcce7f3d6203d45e9d1945a28f69fbfb44f418c44ea73c77de86 + 5c8da28603857d4073c67e751ba3cd526a7ef414135faecfec164e7d01be24be @@ -83,7 +84,7 @@ file://.../tests/_data/infiles/_helpers/local_pckages/b/dist/package-b-23.42.tar.gz PackageSource: Archive - 33d37cf528bc0b20ec8ffd9fa21170e7caadb1b9f15eb559d1937fa4c82d3d40 + 20e983935a800046222a02674ed37baf3e7a4ef7cd40e6033d9c0efaeb73206f @@ -93,9 +94,7 @@ 23.42 some package C - - Apache-2.0 - + Apache-2.0 OR MIT diff --git a/tests/_data/snapshots/environment/plain_local_1.5.json.bin b/tests/_data/snapshots/environment/plain_local_1.5.json.bin index 948eeb0b..ec24b2d8 100644 --- a/tests/_data/snapshots/environment/plain_local_1.5.json.bin +++ b/tests/_data/snapshots/environment/plain_local_1.5.json.bin @@ -9,7 +9,7 @@ "hashes": [ { "alg": "SHA-256", - "content": "4f37ac4a44c1dcce7f3d6203d45e9d1945a28f69fbfb44f418c44ea73c77de86" + "content": "5c8da28603857d4073c67e751ba3cd526a7ef414135faecfec164e7d01be24be" } ], "type": "distribution", @@ -19,7 +19,11 @@ "licenses": [ { "license": { - "id": "Apache-2.0" + "name": "declared license of 'package-a'", + "text": { + "content": "some license text", + "contentType": "text/plain" + } } } ], @@ -36,7 +40,7 @@ "hashes": [ { "alg": "SHA-256", - "content": "33d37cf528bc0b20ec8ffd9fa21170e7caadb1b9f15eb559d1937fa4c82d3d40" + "content": "20e983935a800046222a02674ed37baf3e7a4ef7cd40e6033d9c0efaeb73206f" } ], "type": "distribution", @@ -66,9 +70,7 @@ ], "licenses": [ { - "license": { - "id": "Apache-2.0" - } + "expression": "Apache-2.0 OR MIT" } ], "name": "package-c", diff --git a/tests/_data/snapshots/environment/plain_local_1.5.xml.bin b/tests/_data/snapshots/environment/plain_local_1.5.xml.bin index 926dc9b3..a59e09f4 100644 --- a/tests/_data/snapshots/environment/plain_local_1.5.xml.bin +++ b/tests/_data/snapshots/environment/plain_local_1.5.xml.bin @@ -56,7 +56,8 @@ some package A - Apache-2.0 + declared license of 'package-a' + some license text @@ -64,7 +65,7 @@ file://.../tests/_data/infiles/_helpers/local_pckages/a/dist/package_a-23.42-py3-none-any.whl PackageSource: Archive - 4f37ac4a44c1dcce7f3d6203d45e9d1945a28f69fbfb44f418c44ea73c77de86 + 5c8da28603857d4073c67e751ba3cd526a7ef414135faecfec164e7d01be24be @@ -83,7 +84,7 @@ file://.../tests/_data/infiles/_helpers/local_pckages/b/dist/package-b-23.42.tar.gz PackageSource: Archive - 33d37cf528bc0b20ec8ffd9fa21170e7caadb1b9f15eb559d1937fa4c82d3d40 + 20e983935a800046222a02674ed37baf3e7a4ef7cd40e6033d9c0efaeb73206f @@ -93,9 +94,7 @@ 23.42 some package C - - Apache-2.0 - + Apache-2.0 OR MIT diff --git a/tests/_data/snapshots/environment/plain_normalize-packagename_1.1.xml.bin b/tests/_data/snapshots/environment/plain_normalize-packagename_1.1.xml.bin index 8a805ef6..4c33f517 100644 --- a/tests/_data/snapshots/environment/plain_normalize-packagename_1.1.xml.bin +++ b/tests/_data/snapshots/environment/plain_normalize-packagename_1.1.xml.bin @@ -10,7 +10,8 @@ MIT - MIT license + declared license of 'ruamel.yaml' + MIT license pkg:pypi/ruamel.yaml@0.18.5 diff --git a/tests/_data/snapshots/environment/plain_normalize-packagename_1.2.json.bin b/tests/_data/snapshots/environment/plain_normalize-packagename_1.2.json.bin index 7993a957..bf95cfa4 100644 --- a/tests/_data/snapshots/environment/plain_normalize-packagename_1.2.json.bin +++ b/tests/_data/snapshots/environment/plain_normalize-packagename_1.2.json.bin @@ -33,7 +33,11 @@ }, { "license": { - "name": "MIT license" + "name": "declared license of 'ruamel.yaml'", + "text": { + "content": "MIT license", + "contentType": "text/plain" + } } } ], diff --git a/tests/_data/snapshots/environment/plain_normalize-packagename_1.2.xml.bin b/tests/_data/snapshots/environment/plain_normalize-packagename_1.2.xml.bin index 7f18d55c..ce3a500b 100644 --- a/tests/_data/snapshots/environment/plain_normalize-packagename_1.2.xml.bin +++ b/tests/_data/snapshots/environment/plain_normalize-packagename_1.2.xml.bin @@ -29,7 +29,8 @@ MIT - MIT license + declared license of 'ruamel.yaml' + MIT license pkg:pypi/ruamel.yaml@0.18.5 diff --git a/tests/_data/snapshots/environment/plain_normalize-packagename_1.3.json.bin b/tests/_data/snapshots/environment/plain_normalize-packagename_1.3.json.bin index e7434491..4d73455c 100644 --- a/tests/_data/snapshots/environment/plain_normalize-packagename_1.3.json.bin +++ b/tests/_data/snapshots/environment/plain_normalize-packagename_1.3.json.bin @@ -33,7 +33,11 @@ }, { "license": { - "name": "MIT license" + "name": "declared license of 'ruamel.yaml'", + "text": { + "content": "MIT license", + "contentType": "text/plain" + } } } ], diff --git a/tests/_data/snapshots/environment/plain_normalize-packagename_1.3.xml.bin b/tests/_data/snapshots/environment/plain_normalize-packagename_1.3.xml.bin index c2539a80..75be771b 100644 --- a/tests/_data/snapshots/environment/plain_normalize-packagename_1.3.xml.bin +++ b/tests/_data/snapshots/environment/plain_normalize-packagename_1.3.xml.bin @@ -32,7 +32,8 @@ MIT - MIT license + declared license of 'ruamel.yaml' + MIT license pkg:pypi/ruamel.yaml@0.18.5 diff --git a/tests/_data/snapshots/environment/plain_normalize-packagename_1.4.json.bin b/tests/_data/snapshots/environment/plain_normalize-packagename_1.4.json.bin index cbe7949b..ba9ed46a 100644 --- a/tests/_data/snapshots/environment/plain_normalize-packagename_1.4.json.bin +++ b/tests/_data/snapshots/environment/plain_normalize-packagename_1.4.json.bin @@ -33,7 +33,11 @@ }, { "license": { - "name": "MIT license" + "name": "declared license of 'ruamel.yaml'", + "text": { + "content": "MIT license", + "contentType": "text/plain" + } } } ], diff --git a/tests/_data/snapshots/environment/plain_normalize-packagename_1.4.xml.bin b/tests/_data/snapshots/environment/plain_normalize-packagename_1.4.xml.bin index 356f25ac..deded9be 100644 --- a/tests/_data/snapshots/environment/plain_normalize-packagename_1.4.xml.bin +++ b/tests/_data/snapshots/environment/plain_normalize-packagename_1.4.xml.bin @@ -59,7 +59,8 @@ MIT - MIT license + declared license of 'ruamel.yaml' + MIT license pkg:pypi/ruamel.yaml@0.18.5 diff --git a/tests/_data/snapshots/environment/plain_normalize-packagename_1.5.json.bin b/tests/_data/snapshots/environment/plain_normalize-packagename_1.5.json.bin index 47e61ad6..05011519 100644 --- a/tests/_data/snapshots/environment/plain_normalize-packagename_1.5.json.bin +++ b/tests/_data/snapshots/environment/plain_normalize-packagename_1.5.json.bin @@ -33,7 +33,11 @@ }, { "license": { - "name": "MIT license" + "name": "declared license of 'ruamel.yaml'", + "text": { + "content": "MIT license", + "contentType": "text/plain" + } } } ], diff --git a/tests/_data/snapshots/environment/plain_normalize-packagename_1.5.xml.bin b/tests/_data/snapshots/environment/plain_normalize-packagename_1.5.xml.bin index 4aae0de7..efdf8ff9 100644 --- a/tests/_data/snapshots/environment/plain_normalize-packagename_1.5.xml.bin +++ b/tests/_data/snapshots/environment/plain_normalize-packagename_1.5.xml.bin @@ -59,7 +59,8 @@ MIT - MIT license + declared license of 'ruamel.yaml' + MIT license pkg:pypi/ruamel.yaml@0.18.5 diff --git a/tests/_data/snapshots/environment/plain_with-extras_1.1.xml.bin b/tests/_data/snapshots/environment/plain_with-extras_1.1.xml.bin index 8e7c5574..66824561 100644 --- a/tests/_data/snapshots/environment/plain_with-extras_1.1.xml.bin +++ b/tests/_data/snapshots/environment/plain_with-extras_1.1.xml.bin @@ -117,7 +117,8 @@ Python-2.0 - PSFL + declared license of 'defusedxml' + PSFL pkg:pypi/defusedxml@0.7.1 @@ -138,7 +139,8 @@ Validates fully-qualified domain names against RFC 1123, so that they are acceptable to modern bowsers - MPL 2.0 + declared license of 'fqdn' + MPL 2.0 pkg:pypi/fqdn@1.5.1 @@ -194,7 +196,8 @@ ISC - UNKNOWN + declared license of 'isoduration' + UNKNOWN pkg:pypi/isoduration@20.11.0 @@ -223,7 +226,8 @@ Identify specific nodes in a JSON document (RFC 6901) - Modified BSD License + declared license of 'jsonpointer' + Modified BSD License pkg:pypi/jsonpointer@2.4 @@ -415,7 +419,8 @@ Extensions to the standard Python datetime module - Dual License + declared license of 'python-dateutil' + Dual License pkg:pypi/python-dateutil@2.8.2 @@ -480,7 +485,8 @@ MIT - MIT license + declared license of 'rfc3339-validator' + MIT license pkg:pypi/rfc3339-validator@0.1.4 @@ -500,7 +506,8 @@ GPL-3.0-or-later - GNU GPLv3+ + declared license of 'rfc3987' + GNU GPLv3+ pkg:pypi/rfc3987@1.3.8 @@ -575,7 +582,8 @@ Sorted Containers -- Sorted List, Sorted Dict, Sorted Set - Apache 2.0 + declared license of 'sortedcontainers' + Apache 2.0 pkg:pypi/sortedcontainers@2.4.0 @@ -592,7 +600,8 @@ Typing stubs for python-dateutil - Apache-2.0 license + declared license of 'types-python-dateutil' + Apache-2.0 license pkg:pypi/types-python-dateutil@2.8.19.14 @@ -628,7 +637,8 @@ MIT - MIT License + declared license of 'uri-template' + MIT License pkg:pypi/uri-template@1.3.0 diff --git a/tests/_data/snapshots/environment/plain_with-extras_1.2.json.bin b/tests/_data/snapshots/environment/plain_with-extras_1.2.json.bin index 5947ad69..d9573345 100644 --- a/tests/_data/snapshots/environment/plain_with-extras_1.2.json.bin +++ b/tests/_data/snapshots/environment/plain_with-extras_1.2.json.bin @@ -159,7 +159,11 @@ }, { "license": { - "name": "PSFL" + "name": "declared license of 'defusedxml'", + "text": { + "content": "PSFL", + "contentType": "text/plain" + } } } ], @@ -181,7 +185,11 @@ "licenses": [ { "license": { - "name": "MPL 2.0" + "name": "declared license of 'fqdn'", + "text": { + "content": "MPL 2.0", + "contentType": "text/plain" + } } } ], @@ -268,7 +276,11 @@ }, { "license": { - "name": "UNKNOWN" + "name": "declared license of 'isoduration'", + "text": { + "content": "UNKNOWN", + "contentType": "text/plain" + } } } ], @@ -290,7 +302,11 @@ "licenses": [ { "license": { - "name": "Modified BSD License" + "name": "declared license of 'jsonpointer'", + "text": { + "content": "Modified BSD License", + "contentType": "text/plain" + } } } ], @@ -546,7 +562,11 @@ "licenses": [ { "license": { - "name": "Dual License" + "name": "declared license of 'python-dateutil'", + "text": { + "content": "Dual License", + "contentType": "text/plain" + } } } ], @@ -620,7 +640,11 @@ }, { "license": { - "name": "MIT license" + "name": "declared license of 'rfc3339-validator'", + "text": { + "content": "MIT license", + "contentType": "text/plain" + } } } ], @@ -652,7 +676,11 @@ }, { "license": { - "name": "GNU GPLv3+" + "name": "declared license of 'rfc3987'", + "text": { + "content": "GNU GPLv3+", + "contentType": "text/plain" + } } } ], @@ -743,7 +771,11 @@ "licenses": [ { "license": { - "name": "Apache 2.0" + "name": "declared license of 'sortedcontainers'", + "text": { + "content": "Apache 2.0", + "contentType": "text/plain" + } } } ], @@ -785,7 +817,11 @@ "licenses": [ { "license": { - "name": "Apache-2.0 license" + "name": "declared license of 'types-python-dateutil'", + "text": { + "content": "Apache-2.0 license", + "contentType": "text/plain" + } } } ], @@ -812,7 +848,11 @@ }, { "license": { - "name": "MIT License" + "name": "declared license of 'uri-template'", + "text": { + "content": "MIT License", + "contentType": "text/plain" + } } } ], diff --git a/tests/_data/snapshots/environment/plain_with-extras_1.2.xml.bin b/tests/_data/snapshots/environment/plain_with-extras_1.2.xml.bin index 2c3c416c..6d638e79 100644 --- a/tests/_data/snapshots/environment/plain_with-extras_1.2.xml.bin +++ b/tests/_data/snapshots/environment/plain_with-extras_1.2.xml.bin @@ -136,7 +136,8 @@ Python-2.0 - PSFL + declared license of 'defusedxml' + PSFL pkg:pypi/defusedxml@0.7.1 @@ -157,7 +158,8 @@ Validates fully-qualified domain names against RFC 1123, so that they are acceptable to modern bowsers - MPL 2.0 + declared license of 'fqdn' + MPL 2.0 pkg:pypi/fqdn@1.5.1 @@ -213,7 +215,8 @@ ISC - UNKNOWN + declared license of 'isoduration' + UNKNOWN pkg:pypi/isoduration@20.11.0 @@ -242,7 +245,8 @@ Identify specific nodes in a JSON document (RFC 6901) - Modified BSD License + declared license of 'jsonpointer' + Modified BSD License pkg:pypi/jsonpointer@2.4 @@ -434,7 +438,8 @@ Extensions to the standard Python datetime module - Dual License + declared license of 'python-dateutil' + Dual License pkg:pypi/python-dateutil@2.8.2 @@ -499,7 +504,8 @@ MIT - MIT license + declared license of 'rfc3339-validator' + MIT license pkg:pypi/rfc3339-validator@0.1.4 @@ -519,7 +525,8 @@ GPL-3.0-or-later - GNU GPLv3+ + declared license of 'rfc3987' + GNU GPLv3+ pkg:pypi/rfc3987@1.3.8 @@ -594,7 +601,8 @@ Sorted Containers -- Sorted List, Sorted Dict, Sorted Set - Apache 2.0 + declared license of 'sortedcontainers' + Apache 2.0 pkg:pypi/sortedcontainers@2.4.0 @@ -611,7 +619,8 @@ Typing stubs for python-dateutil - Apache-2.0 license + declared license of 'types-python-dateutil' + Apache-2.0 license pkg:pypi/types-python-dateutil@2.8.19.14 @@ -647,7 +656,8 @@ MIT - MIT License + declared license of 'uri-template' + MIT License pkg:pypi/uri-template@1.3.0 diff --git a/tests/_data/snapshots/environment/plain_with-extras_1.3.json.bin b/tests/_data/snapshots/environment/plain_with-extras_1.3.json.bin index ac47eb8a..673d3a4d 100644 --- a/tests/_data/snapshots/environment/plain_with-extras_1.3.json.bin +++ b/tests/_data/snapshots/environment/plain_with-extras_1.3.json.bin @@ -165,7 +165,11 @@ }, { "license": { - "name": "PSFL" + "name": "declared license of 'defusedxml'", + "text": { + "content": "PSFL", + "contentType": "text/plain" + } } } ], @@ -187,7 +191,11 @@ "licenses": [ { "license": { - "name": "MPL 2.0" + "name": "declared license of 'fqdn'", + "text": { + "content": "MPL 2.0", + "contentType": "text/plain" + } } } ], @@ -274,7 +282,11 @@ }, { "license": { - "name": "UNKNOWN" + "name": "declared license of 'isoduration'", + "text": { + "content": "UNKNOWN", + "contentType": "text/plain" + } } } ], @@ -296,7 +308,11 @@ "licenses": [ { "license": { - "name": "Modified BSD License" + "name": "declared license of 'jsonpointer'", + "text": { + "content": "Modified BSD License", + "contentType": "text/plain" + } } } ], @@ -558,7 +574,11 @@ "licenses": [ { "license": { - "name": "Dual License" + "name": "declared license of 'python-dateutil'", + "text": { + "content": "Dual License", + "contentType": "text/plain" + } } } ], @@ -632,7 +652,11 @@ }, { "license": { - "name": "MIT license" + "name": "declared license of 'rfc3339-validator'", + "text": { + "content": "MIT license", + "contentType": "text/plain" + } } } ], @@ -664,7 +688,11 @@ }, { "license": { - "name": "GNU GPLv3+" + "name": "declared license of 'rfc3987'", + "text": { + "content": "GNU GPLv3+", + "contentType": "text/plain" + } } } ], @@ -755,7 +783,11 @@ "licenses": [ { "license": { - "name": "Apache 2.0" + "name": "declared license of 'sortedcontainers'", + "text": { + "content": "Apache 2.0", + "contentType": "text/plain" + } } } ], @@ -797,7 +829,11 @@ "licenses": [ { "license": { - "name": "Apache-2.0 license" + "name": "declared license of 'types-python-dateutil'", + "text": { + "content": "Apache-2.0 license", + "contentType": "text/plain" + } } } ], @@ -824,7 +860,11 @@ }, { "license": { - "name": "MIT License" + "name": "declared license of 'uri-template'", + "text": { + "content": "MIT License", + "contentType": "text/plain" + } } } ], diff --git a/tests/_data/snapshots/environment/plain_with-extras_1.3.xml.bin b/tests/_data/snapshots/environment/plain_with-extras_1.3.xml.bin index 984c9fee..deb346e6 100644 --- a/tests/_data/snapshots/environment/plain_with-extras_1.3.xml.bin +++ b/tests/_data/snapshots/environment/plain_with-extras_1.3.xml.bin @@ -142,7 +142,8 @@ Python-2.0 - PSFL + declared license of 'defusedxml' + PSFL pkg:pypi/defusedxml@0.7.1 @@ -163,7 +164,8 @@ Validates fully-qualified domain names against RFC 1123, so that they are acceptable to modern bowsers - MPL 2.0 + declared license of 'fqdn' + MPL 2.0 pkg:pypi/fqdn@1.5.1 @@ -219,7 +221,8 @@ ISC - UNKNOWN + declared license of 'isoduration' + UNKNOWN pkg:pypi/isoduration@20.11.0 @@ -248,7 +251,8 @@ Identify specific nodes in a JSON document (RFC 6901) - Modified BSD License + declared license of 'jsonpointer' + Modified BSD License pkg:pypi/jsonpointer@2.4 @@ -443,7 +447,8 @@ Extensions to the standard Python datetime module - Dual License + declared license of 'python-dateutil' + Dual License pkg:pypi/python-dateutil@2.8.2 @@ -508,7 +513,8 @@ MIT - MIT license + declared license of 'rfc3339-validator' + MIT license pkg:pypi/rfc3339-validator@0.1.4 @@ -528,7 +534,8 @@ GPL-3.0-or-later - GNU GPLv3+ + declared license of 'rfc3987' + GNU GPLv3+ pkg:pypi/rfc3987@1.3.8 @@ -603,7 +610,8 @@ Sorted Containers -- Sorted List, Sorted Dict, Sorted Set - Apache 2.0 + declared license of 'sortedcontainers' + Apache 2.0 pkg:pypi/sortedcontainers@2.4.0 @@ -620,7 +628,8 @@ Typing stubs for python-dateutil - Apache-2.0 license + declared license of 'types-python-dateutil' + Apache-2.0 license pkg:pypi/types-python-dateutil@2.8.19.14 @@ -656,7 +665,8 @@ MIT - MIT License + declared license of 'uri-template' + MIT License pkg:pypi/uri-template@1.3.0 diff --git a/tests/_data/snapshots/environment/plain_with-extras_1.4.json.bin b/tests/_data/snapshots/environment/plain_with-extras_1.4.json.bin index 354a3737..25ea23d5 100644 --- a/tests/_data/snapshots/environment/plain_with-extras_1.4.json.bin +++ b/tests/_data/snapshots/environment/plain_with-extras_1.4.json.bin @@ -165,7 +165,11 @@ }, { "license": { - "name": "PSFL" + "name": "declared license of 'defusedxml'", + "text": { + "content": "PSFL", + "contentType": "text/plain" + } } } ], @@ -187,7 +191,11 @@ "licenses": [ { "license": { - "name": "MPL 2.0" + "name": "declared license of 'fqdn'", + "text": { + "content": "MPL 2.0", + "contentType": "text/plain" + } } } ], @@ -274,7 +282,11 @@ }, { "license": { - "name": "UNKNOWN" + "name": "declared license of 'isoduration'", + "text": { + "content": "UNKNOWN", + "contentType": "text/plain" + } } } ], @@ -296,7 +308,11 @@ "licenses": [ { "license": { - "name": "Modified BSD License" + "name": "declared license of 'jsonpointer'", + "text": { + "content": "Modified BSD License", + "contentType": "text/plain" + } } } ], @@ -558,7 +574,11 @@ "licenses": [ { "license": { - "name": "Dual License" + "name": "declared license of 'python-dateutil'", + "text": { + "content": "Dual License", + "contentType": "text/plain" + } } } ], @@ -632,7 +652,11 @@ }, { "license": { - "name": "MIT license" + "name": "declared license of 'rfc3339-validator'", + "text": { + "content": "MIT license", + "contentType": "text/plain" + } } } ], @@ -664,7 +688,11 @@ }, { "license": { - "name": "GNU GPLv3+" + "name": "declared license of 'rfc3987'", + "text": { + "content": "GNU GPLv3+", + "contentType": "text/plain" + } } } ], @@ -755,7 +783,11 @@ "licenses": [ { "license": { - "name": "Apache 2.0" + "name": "declared license of 'sortedcontainers'", + "text": { + "content": "Apache 2.0", + "contentType": "text/plain" + } } } ], @@ -797,7 +829,11 @@ "licenses": [ { "license": { - "name": "Apache-2.0 license" + "name": "declared license of 'types-python-dateutil'", + "text": { + "content": "Apache-2.0 license", + "contentType": "text/plain" + } } } ], @@ -824,7 +860,11 @@ }, { "license": { - "name": "MIT License" + "name": "declared license of 'uri-template'", + "text": { + "content": "MIT License", + "contentType": "text/plain" + } } } ], diff --git a/tests/_data/snapshots/environment/plain_with-extras_1.4.xml.bin b/tests/_data/snapshots/environment/plain_with-extras_1.4.xml.bin index 6d289b3f..91dd03a1 100644 --- a/tests/_data/snapshots/environment/plain_with-extras_1.4.xml.bin +++ b/tests/_data/snapshots/environment/plain_with-extras_1.4.xml.bin @@ -169,7 +169,8 @@ Python-2.0 - PSFL + declared license of 'defusedxml' + PSFL pkg:pypi/defusedxml@0.7.1 @@ -190,7 +191,8 @@ Validates fully-qualified domain names against RFC 1123, so that they are acceptable to modern bowsers - MPL 2.0 + declared license of 'fqdn' + MPL 2.0 pkg:pypi/fqdn@1.5.1 @@ -246,7 +248,8 @@ ISC - UNKNOWN + declared license of 'isoduration' + UNKNOWN pkg:pypi/isoduration@20.11.0 @@ -275,7 +278,8 @@ Identify specific nodes in a JSON document (RFC 6901) - Modified BSD License + declared license of 'jsonpointer' + Modified BSD License pkg:pypi/jsonpointer@2.4 @@ -470,7 +474,8 @@ Extensions to the standard Python datetime module - Dual License + declared license of 'python-dateutil' + Dual License pkg:pypi/python-dateutil@2.8.2 @@ -535,7 +540,8 @@ MIT - MIT license + declared license of 'rfc3339-validator' + MIT license pkg:pypi/rfc3339-validator@0.1.4 @@ -555,7 +561,8 @@ GPL-3.0-or-later - GNU GPLv3+ + declared license of 'rfc3987' + GNU GPLv3+ pkg:pypi/rfc3987@1.3.8 @@ -630,7 +637,8 @@ Sorted Containers -- Sorted List, Sorted Dict, Sorted Set - Apache 2.0 + declared license of 'sortedcontainers' + Apache 2.0 pkg:pypi/sortedcontainers@2.4.0 @@ -647,7 +655,8 @@ Typing stubs for python-dateutil - Apache-2.0 license + declared license of 'types-python-dateutil' + Apache-2.0 license pkg:pypi/types-python-dateutil@2.8.19.14 @@ -683,7 +692,8 @@ MIT - MIT License + declared license of 'uri-template' + MIT License pkg:pypi/uri-template@1.3.0 diff --git a/tests/_data/snapshots/environment/plain_with-extras_1.5.json.bin b/tests/_data/snapshots/environment/plain_with-extras_1.5.json.bin index 147b5ec9..79464274 100644 --- a/tests/_data/snapshots/environment/plain_with-extras_1.5.json.bin +++ b/tests/_data/snapshots/environment/plain_with-extras_1.5.json.bin @@ -165,7 +165,11 @@ }, { "license": { - "name": "PSFL" + "name": "declared license of 'defusedxml'", + "text": { + "content": "PSFL", + "contentType": "text/plain" + } } } ], @@ -187,7 +191,11 @@ "licenses": [ { "license": { - "name": "MPL 2.0" + "name": "declared license of 'fqdn'", + "text": { + "content": "MPL 2.0", + "contentType": "text/plain" + } } } ], @@ -274,7 +282,11 @@ }, { "license": { - "name": "UNKNOWN" + "name": "declared license of 'isoduration'", + "text": { + "content": "UNKNOWN", + "contentType": "text/plain" + } } } ], @@ -296,7 +308,11 @@ "licenses": [ { "license": { - "name": "Modified BSD License" + "name": "declared license of 'jsonpointer'", + "text": { + "content": "Modified BSD License", + "contentType": "text/plain" + } } } ], @@ -558,7 +574,11 @@ "licenses": [ { "license": { - "name": "Dual License" + "name": "declared license of 'python-dateutil'", + "text": { + "content": "Dual License", + "contentType": "text/plain" + } } } ], @@ -632,7 +652,11 @@ }, { "license": { - "name": "MIT license" + "name": "declared license of 'rfc3339-validator'", + "text": { + "content": "MIT license", + "contentType": "text/plain" + } } } ], @@ -664,7 +688,11 @@ }, { "license": { - "name": "GNU GPLv3+" + "name": "declared license of 'rfc3987'", + "text": { + "content": "GNU GPLv3+", + "contentType": "text/plain" + } } } ], @@ -755,7 +783,11 @@ "licenses": [ { "license": { - "name": "Apache 2.0" + "name": "declared license of 'sortedcontainers'", + "text": { + "content": "Apache 2.0", + "contentType": "text/plain" + } } } ], @@ -797,7 +829,11 @@ "licenses": [ { "license": { - "name": "Apache-2.0 license" + "name": "declared license of 'types-python-dateutil'", + "text": { + "content": "Apache-2.0 license", + "contentType": "text/plain" + } } } ], @@ -824,7 +860,11 @@ }, { "license": { - "name": "MIT License" + "name": "declared license of 'uri-template'", + "text": { + "content": "MIT License", + "contentType": "text/plain" + } } } ], diff --git a/tests/_data/snapshots/environment/plain_with-extras_1.5.xml.bin b/tests/_data/snapshots/environment/plain_with-extras_1.5.xml.bin index 1606c3ec..295897a7 100644 --- a/tests/_data/snapshots/environment/plain_with-extras_1.5.xml.bin +++ b/tests/_data/snapshots/environment/plain_with-extras_1.5.xml.bin @@ -169,7 +169,8 @@ Python-2.0 - PSFL + declared license of 'defusedxml' + PSFL pkg:pypi/defusedxml@0.7.1 @@ -190,7 +191,8 @@ Validates fully-qualified domain names against RFC 1123, so that they are acceptable to modern bowsers - MPL 2.0 + declared license of 'fqdn' + MPL 2.0 pkg:pypi/fqdn@1.5.1 @@ -246,7 +248,8 @@ ISC - UNKNOWN + declared license of 'isoduration' + UNKNOWN pkg:pypi/isoduration@20.11.0 @@ -275,7 +278,8 @@ Identify specific nodes in a JSON document (RFC 6901) - Modified BSD License + declared license of 'jsonpointer' + Modified BSD License pkg:pypi/jsonpointer@2.4 @@ -470,7 +474,8 @@ Extensions to the standard Python datetime module - Dual License + declared license of 'python-dateutil' + Dual License pkg:pypi/python-dateutil@2.8.2 @@ -535,7 +540,8 @@ MIT - MIT license + declared license of 'rfc3339-validator' + MIT license pkg:pypi/rfc3339-validator@0.1.4 @@ -555,7 +561,8 @@ GPL-3.0-or-later - GNU GPLv3+ + declared license of 'rfc3987' + GNU GPLv3+ pkg:pypi/rfc3987@1.3.8 @@ -630,7 +637,8 @@ Sorted Containers -- Sorted List, Sorted Dict, Sorted Set - Apache 2.0 + declared license of 'sortedcontainers' + Apache 2.0 pkg:pypi/sortedcontainers@2.4.0 @@ -647,7 +655,8 @@ Typing stubs for python-dateutil - Apache-2.0 license + declared license of 'types-python-dateutil' + Apache-2.0 license pkg:pypi/types-python-dateutil@2.8.19.14 @@ -683,7 +692,8 @@ MIT - MIT License + declared license of 'uri-template' + MIT License pkg:pypi/uri-template@1.3.0 diff --git a/tests/_data/snapshots/environment/plain_with-license-file_1.0.xml.bin b/tests/_data/snapshots/environment/plain_with-license-file_1.0.xml.bin new file mode 100644 index 00000000..acb06612 --- /dev/null +++ b/tests/_data/snapshots/environment/plain_with-license-file_1.0.xml.bin @@ -0,0 +1,4 @@ + + + + diff --git a/tests/_data/snapshots/environment/plain_with-license-file_1.1.xml.bin b/tests/_data/snapshots/environment/plain_with-license-file_1.1.xml.bin new file mode 100644 index 00000000..640f73ff --- /dev/null +++ b/tests/_data/snapshots/environment/plain_with-license-file_1.1.xml.bin @@ -0,0 +1,4 @@ + + + + diff --git a/tests/_data/snapshots/environment/plain_with-license-file_1.2.json.bin b/tests/_data/snapshots/environment/plain_with-license-file_1.2.json.bin new file mode 100644 index 00000000..1ee914a9 --- /dev/null +++ b/tests/_data/snapshots/environment/plain_with-license-file_1.2.json.bin @@ -0,0 +1,44 @@ +{ + "dependencies": [ + { + "ref": "root-component" + } + ], + "metadata": { + "component": { + "bom-ref": "root-component", + "description": "with licenses from file, instead of SPDX ID/Expression", + "licenses": [ + { + "license": { + "name": "declared license of 'with-license-file'", + "text": { + "content": "VGhpcyBpcyB0aGUgbGljZW5zZSB0ZXh0IG9mIHRoaXMgY29tcG9uZW50LgpJdCBpcyBleHBlY3RlZCB0byBiZSBhdmFpbGFibGUgaW4gYSBTQk9NLgo=", + "contentType": "text/plain", + "encoding": "base64" + } + } + } + ], + "name": "with-license-file", + "type": "application", + "version": "0.1.0" + }, + "tools": [ + { + "name": "cyclonedx-bom", + "vendor": "CycloneDX", + "version": "thisVersion-testing" + }, + { + "name": "cyclonedx-python-lib", + "vendor": "CycloneDX", + "version": "libVersion-testing" + } + ] + }, + "version": 1, + "$schema": "http://cyclonedx.org/schema/bom-1.2b.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.2" +} \ No newline at end of file diff --git a/tests/_data/snapshots/environment/plain_with-license-file_1.2.xml.bin b/tests/_data/snapshots/environment/plain_with-license-file_1.2.xml.bin new file mode 100644 index 00000000..8b335021 --- /dev/null +++ b/tests/_data/snapshots/environment/plain_with-license-file_1.2.xml.bin @@ -0,0 +1,31 @@ + + + + + + CycloneDX + cyclonedx-bom + thisVersion-testing + + + CycloneDX + cyclonedx-python-lib + libVersion-testing + + + + with-license-file + 0.1.0 + with licenses from file, instead of SPDX ID/Expression + + + declared license of 'with-license-file' + VGhpcyBpcyB0aGUgbGljZW5zZSB0ZXh0IG9mIHRoaXMgY29tcG9uZW50LgpJdCBpcyBleHBlY3RlZCB0byBiZSBhdmFpbGFibGUgaW4gYSBTQk9NLgo= + + + + + + + + diff --git a/tests/_data/snapshots/environment/plain_with-license-file_1.3.json.bin b/tests/_data/snapshots/environment/plain_with-license-file_1.3.json.bin new file mode 100644 index 00000000..0c62fac8 --- /dev/null +++ b/tests/_data/snapshots/environment/plain_with-license-file_1.3.json.bin @@ -0,0 +1,50 @@ +{ + "dependencies": [ + { + "ref": "root-component" + } + ], + "metadata": { + "component": { + "bom-ref": "root-component", + "description": "with licenses from file, instead of SPDX ID/Expression", + "licenses": [ + { + "license": { + "name": "declared license of 'with-license-file'", + "text": { + "content": "VGhpcyBpcyB0aGUgbGljZW5zZSB0ZXh0IG9mIHRoaXMgY29tcG9uZW50LgpJdCBpcyBleHBlY3RlZCB0byBiZSBhdmFpbGFibGUgaW4gYSBTQk9NLgo=", + "contentType": "text/plain", + "encoding": "base64" + } + } + } + ], + "name": "with-license-file", + "type": "application", + "version": "0.1.0" + }, + "properties": [ + { + "name": "cdx:reproducible", + "value": "true" + } + ], + "tools": [ + { + "name": "cyclonedx-bom", + "vendor": "CycloneDX", + "version": "thisVersion-testing" + }, + { + "name": "cyclonedx-python-lib", + "vendor": "CycloneDX", + "version": "libVersion-testing" + } + ] + }, + "version": 1, + "$schema": "http://cyclonedx.org/schema/bom-1.3a.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.3" +} \ No newline at end of file diff --git a/tests/_data/snapshots/environment/plain_with-license-file_1.3.xml.bin b/tests/_data/snapshots/environment/plain_with-license-file_1.3.xml.bin new file mode 100644 index 00000000..ca266c8c --- /dev/null +++ b/tests/_data/snapshots/environment/plain_with-license-file_1.3.xml.bin @@ -0,0 +1,34 @@ + + + + + + CycloneDX + cyclonedx-bom + thisVersion-testing + + + CycloneDX + cyclonedx-python-lib + libVersion-testing + + + + with-license-file + 0.1.0 + with licenses from file, instead of SPDX ID/Expression + + + declared license of 'with-license-file' + VGhpcyBpcyB0aGUgbGljZW5zZSB0ZXh0IG9mIHRoaXMgY29tcG9uZW50LgpJdCBpcyBleHBlY3RlZCB0byBiZSBhdmFpbGFibGUgaW4gYSBTQk9NLgo= + + + + + true + + + + + + diff --git a/tests/_data/snapshots/environment/plain_with-license-file_1.4.json.bin b/tests/_data/snapshots/environment/plain_with-license-file_1.4.json.bin new file mode 100644 index 00000000..c913eef1 --- /dev/null +++ b/tests/_data/snapshots/environment/plain_with-license-file_1.4.json.bin @@ -0,0 +1,46 @@ +{ + "dependencies": [ + { + "ref": "root-component" + } + ], + "metadata": { + "component": { + "bom-ref": "root-component", + "description": "with licenses from file, instead of SPDX ID/Expression", + "licenses": [ + { + "license": { + "name": "declared license of 'with-license-file'", + "text": { + "content": "VGhpcyBpcyB0aGUgbGljZW5zZSB0ZXh0IG9mIHRoaXMgY29tcG9uZW50LgpJdCBpcyBleHBlY3RlZCB0byBiZSBhdmFpbGFibGUgaW4gYSBTQk9NLgo=", + "contentType": "text/plain", + "encoding": "base64" + } + } + } + ], + "name": "with-license-file", + "type": "application", + "version": "0.1.0" + }, + "properties": [ + { + "name": "cdx:reproducible", + "value": "true" + } + ], + "tools": [ + { + "externalReferences": [ ], + "name": "cyclonedx-python-lib", + "vendor": "CycloneDX", + "version": "libVersion-testing" + } + ] + }, + "version": 1, + "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.4" +} \ No newline at end of file diff --git a/tests/_data/snapshots/environment/plain_with-license-file_1.4.xml.bin b/tests/_data/snapshots/environment/plain_with-license-file_1.4.xml.bin new file mode 100644 index 00000000..51e9cbe4 --- /dev/null +++ b/tests/_data/snapshots/environment/plain_with-license-file_1.4.xml.bin @@ -0,0 +1,61 @@ + + + + + + CycloneDX + cyclonedx-bom + thisVersion-testing + + + https://github.com/CycloneDX/cyclonedx-python/actions + + + https://pypi.org/project/cyclonedx-bom/ + + + https://cyclonedx-bom-tool.readthedocs.io/ + + + https://github.com/CycloneDX/cyclonedx-python/issues + + + https://github.com/CycloneDX/cyclonedx-python/blob/main/LICENSE + + + https://github.com/CycloneDX/cyclonedx-python/blob/main/CHANGELOG.md + + + https://github.com/CycloneDX/cyclonedx-python/ + + + https://github.com/CycloneDX/cyclonedx-python/#readme + + + + + CycloneDX + cyclonedx-python-lib + libVersion-testing + + + + + with-license-file + 0.1.0 + with licenses from file, instead of SPDX ID/Expression + + + declared license of 'with-license-file' + VGhpcyBpcyB0aGUgbGljZW5zZSB0ZXh0IG9mIHRoaXMgY29tcG9uZW50LgpJdCBpcyBleHBlY3RlZCB0byBiZSBhdmFpbGFibGUgaW4gYSBTQk9NLgo= + + + + + true + + + + + + diff --git a/tests/_data/snapshots/environment/plain_with-license-file_1.5.json.bin b/tests/_data/snapshots/environment/plain_with-license-file_1.5.json.bin new file mode 100644 index 00000000..01298deb --- /dev/null +++ b/tests/_data/snapshots/environment/plain_with-license-file_1.5.json.bin @@ -0,0 +1,46 @@ +{ + "dependencies": [ + { + "ref": "root-component" + } + ], + "metadata": { + "component": { + "bom-ref": "root-component", + "description": "with licenses from file, instead of SPDX ID/Expression", + "licenses": [ + { + "license": { + "name": "declared license of 'with-license-file'", + "text": { + "content": "VGhpcyBpcyB0aGUgbGljZW5zZSB0ZXh0IG9mIHRoaXMgY29tcG9uZW50LgpJdCBpcyBleHBlY3RlZCB0byBiZSBhdmFpbGFibGUgaW4gYSBTQk9NLgo=", + "contentType": "text/plain", + "encoding": "base64" + } + } + } + ], + "name": "with-license-file", + "type": "application", + "version": "0.1.0" + }, + "properties": [ + { + "name": "cdx:reproducible", + "value": "true" + } + ], + "tools": [ + { + "externalReferences": [ ], + "name": "cyclonedx-python-lib", + "vendor": "CycloneDX", + "version": "libVersion-testing" + } + ] + }, + "version": 1, + "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.5" +} \ No newline at end of file diff --git a/tests/_data/snapshots/environment/plain_with-license-file_1.5.xml.bin b/tests/_data/snapshots/environment/plain_with-license-file_1.5.xml.bin new file mode 100644 index 00000000..0dc1b63d --- /dev/null +++ b/tests/_data/snapshots/environment/plain_with-license-file_1.5.xml.bin @@ -0,0 +1,61 @@ + + + + + + CycloneDX + cyclonedx-bom + thisVersion-testing + + + https://github.com/CycloneDX/cyclonedx-python/actions + + + https://pypi.org/project/cyclonedx-bom/ + + + https://cyclonedx-bom-tool.readthedocs.io/ + + + https://github.com/CycloneDX/cyclonedx-python/issues + + + https://github.com/CycloneDX/cyclonedx-python/blob/main/LICENSE + + + https://github.com/CycloneDX/cyclonedx-python/blob/main/CHANGELOG.md + + + https://github.com/CycloneDX/cyclonedx-python/ + + + https://github.com/CycloneDX/cyclonedx-python/#readme + + + + + CycloneDX + cyclonedx-python-lib + libVersion-testing + + + + + with-license-file + 0.1.0 + with licenses from file, instead of SPDX ID/Expression + + + declared license of 'with-license-file' + VGhpcyBpcyB0aGUgbGljZW5zZSB0ZXh0IG9mIHRoaXMgY29tcG9uZW50LgpJdCBpcyBleHBlY3RlZCB0byBiZSBhdmFpbGFibGUgaW4gYSBTQk9NLgo= + + + + + true + + + + + + diff --git a/tests/_data/snapshots/environment/plain_with-license-text_1.0.xml.bin b/tests/_data/snapshots/environment/plain_with-license-text_1.0.xml.bin new file mode 100644 index 00000000..13deb487 --- /dev/null +++ b/tests/_data/snapshots/environment/plain_with-license-text_1.0.xml.bin @@ -0,0 +1,23 @@ + + + + + package-a + 23.42 + some package A + false + + + package-b + 23.42 + some package B + false + + + package-c + 23.42 + some package C + false + + + diff --git a/tests/_data/snapshots/environment/plain_with-license-text_1.1.xml.bin b/tests/_data/snapshots/environment/plain_with-license-text_1.1.xml.bin new file mode 100644 index 00000000..b57c90f3 --- /dev/null +++ b/tests/_data/snapshots/environment/plain_with-license-text_1.1.xml.bin @@ -0,0 +1,52 @@ + + + + + package-a + 23.42 + some package A + + + declared license of 'package-a' + some license text + + + + + file://.../tests/_data/infiles/_helpers/local_pckages/a/dist/package_a-23.42-py3-none-any.whl + PackageSource: Archive + + + + + package-b + 23.42 + some package B + + + Apache-2.0 + + + + + file://.../tests/_data/infiles/_helpers/local_pckages/b/dist/package_b-23.42-py3-none-any.whl + PackageSource: Archive + + + + + package-c + 23.42 + some package C + + Apache-2.0 OR MIT + + + + file://.../tests/_data/infiles/_helpers/local_pckages/c/dist/package_c-23.42-py3-none-any.whl + PackageSource: Archive + + + + + diff --git a/tests/_data/snapshots/environment/plain_with-license-text_1.2.json.bin b/tests/_data/snapshots/environment/plain_with-license-text_1.2.json.bin new file mode 100644 index 00000000..a07cf4c4 --- /dev/null +++ b/tests/_data/snapshots/environment/plain_with-license-text_1.2.json.bin @@ -0,0 +1,119 @@ +{ + "components": [ + { + "bom-ref": "package-a==23.42", + "description": "some package A", + "externalReferences": [ + { + "comment": "PackageSource: Archive", + "type": "distribution", + "url": "file://.../tests/_data/infiles/_helpers/local_pckages/a/dist/package_a-23.42-py3-none-any.whl" + } + ], + "licenses": [ + { + "license": { + "name": "declared license of 'package-a'", + "text": { + "content": "some license text", + "contentType": "text/plain" + } + } + } + ], + "name": "package-a", + "type": "library", + "version": "23.42" + }, + { + "bom-ref": "package-b==23.42", + "description": "some package B", + "externalReferences": [ + { + "comment": "PackageSource: Archive", + "type": "distribution", + "url": "file://.../tests/_data/infiles/_helpers/local_pckages/b/dist/package_b-23.42-py3-none-any.whl" + } + ], + "licenses": [ + { + "license": { + "id": "Apache-2.0" + } + } + ], + "name": "package-b", + "type": "library", + "version": "23.42" + }, + { + "bom-ref": "package-c==23.42", + "description": "some package C", + "externalReferences": [ + { + "comment": "PackageSource: Archive", + "type": "distribution", + "url": "file://.../tests/_data/infiles/_helpers/local_pckages/c/dist/package_c-23.42-py3-none-any.whl" + } + ], + "licenses": [ + { + "expression": "Apache-2.0 OR MIT" + } + ], + "name": "package-c", + "type": "library", + "version": "23.42" + } + ], + "dependencies": [ + { + "ref": "package-a==23.42" + }, + { + "ref": "package-b==23.42" + }, + { + "ref": "package-c==23.42" + }, + { + "ref": "root-component" + } + ], + "metadata": { + "component": { + "bom-ref": "root-component", + "description": "with licenses as text, instead of SPDX ID/Expression", + "licenses": [ + { + "license": { + "name": "declared license of 'with-license-text'", + "text": { + "content": "This is the license text of this component.\nIt is expected to be available in a SBOM.", + "contentType": "text/plain" + } + } + } + ], + "name": "with-license-text", + "type": "application", + "version": "0.1.0" + }, + "tools": [ + { + "name": "cyclonedx-bom", + "vendor": "CycloneDX", + "version": "thisVersion-testing" + }, + { + "name": "cyclonedx-python-lib", + "vendor": "CycloneDX", + "version": "libVersion-testing" + } + ] + }, + "version": 1, + "$schema": "http://cyclonedx.org/schema/bom-1.2b.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.2" +} \ No newline at end of file diff --git a/tests/_data/snapshots/environment/plain_with-license-text_1.2.xml.bin b/tests/_data/snapshots/environment/plain_with-license-text_1.2.xml.bin new file mode 100644 index 00000000..d924cabd --- /dev/null +++ b/tests/_data/snapshots/environment/plain_with-license-text_1.2.xml.bin @@ -0,0 +1,84 @@ + + + + + + CycloneDX + cyclonedx-bom + thisVersion-testing + + + CycloneDX + cyclonedx-python-lib + libVersion-testing + + + + with-license-text + 0.1.0 + with licenses as text, instead of SPDX ID/Expression + + + declared license of 'with-license-text' + This is the license text of this component. +It is expected to be available in a SBOM. + + + + + + + package-a + 23.42 + some package A + + + declared license of 'package-a' + some license text + + + + + file://.../tests/_data/infiles/_helpers/local_pckages/a/dist/package_a-23.42-py3-none-any.whl + PackageSource: Archive + + + + + package-b + 23.42 + some package B + + + Apache-2.0 + + + + + file://.../tests/_data/infiles/_helpers/local_pckages/b/dist/package_b-23.42-py3-none-any.whl + PackageSource: Archive + + + + + package-c + 23.42 + some package C + + Apache-2.0 OR MIT + + + + file://.../tests/_data/infiles/_helpers/local_pckages/c/dist/package_c-23.42-py3-none-any.whl + PackageSource: Archive + + + + + + + + + + + diff --git a/tests/_data/snapshots/environment/plain_with-license-text_1.3.json.bin b/tests/_data/snapshots/environment/plain_with-license-text_1.3.json.bin new file mode 100644 index 00000000..5fc0ff8c --- /dev/null +++ b/tests/_data/snapshots/environment/plain_with-license-text_1.3.json.bin @@ -0,0 +1,143 @@ +{ + "components": [ + { + "bom-ref": "package-a==23.42", + "description": "some package A", + "externalReferences": [ + { + "comment": "PackageSource: Archive", + "hashes": [ + { + "alg": "SHA-256", + "content": "5c8da28603857d4073c67e751ba3cd526a7ef414135faecfec164e7d01be24be" + } + ], + "type": "distribution", + "url": "file://.../tests/_data/infiles/_helpers/local_pckages/a/dist/package_a-23.42-py3-none-any.whl" + } + ], + "licenses": [ + { + "license": { + "name": "declared license of 'package-a'", + "text": { + "content": "some license text", + "contentType": "text/plain" + } + } + } + ], + "name": "package-a", + "type": "library", + "version": "23.42" + }, + { + "bom-ref": "package-b==23.42", + "description": "some package B", + "externalReferences": [ + { + "comment": "PackageSource: Archive", + "hashes": [ + { + "alg": "SHA-256", + "content": "583f7cb9db5c26194e8004ac82a90d7b46664da8da674919d3e2189c332a1f78" + } + ], + "type": "distribution", + "url": "file://.../tests/_data/infiles/_helpers/local_pckages/b/dist/package_b-23.42-py3-none-any.whl" + } + ], + "licenses": [ + { + "license": { + "id": "Apache-2.0" + } + } + ], + "name": "package-b", + "type": "library", + "version": "23.42" + }, + { + "bom-ref": "package-c==23.42", + "description": "some package C", + "externalReferences": [ + { + "comment": "PackageSource: Archive", + "hashes": [ + { + "alg": "SHA-256", + "content": "c1ac59f18ed20f2e651a37f74134ade2a396e27513ef1c73461873c49058f641" + } + ], + "type": "distribution", + "url": "file://.../tests/_data/infiles/_helpers/local_pckages/c/dist/package_c-23.42-py3-none-any.whl" + } + ], + "licenses": [ + { + "expression": "Apache-2.0 OR MIT" + } + ], + "name": "package-c", + "type": "library", + "version": "23.42" + } + ], + "dependencies": [ + { + "ref": "package-a==23.42" + }, + { + "ref": "package-b==23.42" + }, + { + "ref": "package-c==23.42" + }, + { + "ref": "root-component" + } + ], + "metadata": { + "component": { + "bom-ref": "root-component", + "description": "with licenses as text, instead of SPDX ID/Expression", + "licenses": [ + { + "license": { + "name": "declared license of 'with-license-text'", + "text": { + "content": "This is the license text of this component.\nIt is expected to be available in a SBOM.", + "contentType": "text/plain" + } + } + } + ], + "name": "with-license-text", + "type": "application", + "version": "0.1.0" + }, + "properties": [ + { + "name": "cdx:reproducible", + "value": "true" + } + ], + "tools": [ + { + "name": "cyclonedx-bom", + "vendor": "CycloneDX", + "version": "thisVersion-testing" + }, + { + "name": "cyclonedx-python-lib", + "vendor": "CycloneDX", + "version": "libVersion-testing" + } + ] + }, + "version": 1, + "$schema": "http://cyclonedx.org/schema/bom-1.3a.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.3" +} \ No newline at end of file diff --git a/tests/_data/snapshots/environment/plain_with-license-text_1.3.xml.bin b/tests/_data/snapshots/environment/plain_with-license-text_1.3.xml.bin new file mode 100644 index 00000000..9929fff1 --- /dev/null +++ b/tests/_data/snapshots/environment/plain_with-license-text_1.3.xml.bin @@ -0,0 +1,96 @@ + + + + + + CycloneDX + cyclonedx-bom + thisVersion-testing + + + CycloneDX + cyclonedx-python-lib + libVersion-testing + + + + with-license-text + 0.1.0 + with licenses as text, instead of SPDX ID/Expression + + + declared license of 'with-license-text' + This is the license text of this component. +It is expected to be available in a SBOM. + + + + + true + + + + + package-a + 23.42 + some package A + + + declared license of 'package-a' + some license text + + + + + file://.../tests/_data/infiles/_helpers/local_pckages/a/dist/package_a-23.42-py3-none-any.whl + PackageSource: Archive + + 5c8da28603857d4073c67e751ba3cd526a7ef414135faecfec164e7d01be24be + + + + + + package-b + 23.42 + some package B + + + Apache-2.0 + + + + + file://.../tests/_data/infiles/_helpers/local_pckages/b/dist/package_b-23.42-py3-none-any.whl + PackageSource: Archive + + 583f7cb9db5c26194e8004ac82a90d7b46664da8da674919d3e2189c332a1f78 + + + + + + package-c + 23.42 + some package C + + Apache-2.0 OR MIT + + + + file://.../tests/_data/infiles/_helpers/local_pckages/c/dist/package_c-23.42-py3-none-any.whl + PackageSource: Archive + + c1ac59f18ed20f2e651a37f74134ade2a396e27513ef1c73461873c49058f641 + + + + + + + + + + + + diff --git a/tests/_data/snapshots/environment/plain_with-license-text_1.4.json.bin b/tests/_data/snapshots/environment/plain_with-license-text_1.4.json.bin new file mode 100644 index 00000000..e41eff71 --- /dev/null +++ b/tests/_data/snapshots/environment/plain_with-license-text_1.4.json.bin @@ -0,0 +1,139 @@ +{ + "components": [ + { + "bom-ref": "package-a==23.42", + "description": "some package A", + "externalReferences": [ + { + "comment": "PackageSource: Archive", + "hashes": [ + { + "alg": "SHA-256", + "content": "5c8da28603857d4073c67e751ba3cd526a7ef414135faecfec164e7d01be24be" + } + ], + "type": "distribution", + "url": "file://.../tests/_data/infiles/_helpers/local_pckages/a/dist/package_a-23.42-py3-none-any.whl" + } + ], + "licenses": [ + { + "license": { + "name": "declared license of 'package-a'", + "text": { + "content": "some license text", + "contentType": "text/plain" + } + } + } + ], + "name": "package-a", + "type": "library", + "version": "23.42" + }, + { + "bom-ref": "package-b==23.42", + "description": "some package B", + "externalReferences": [ + { + "comment": "PackageSource: Archive", + "hashes": [ + { + "alg": "SHA-256", + "content": "583f7cb9db5c26194e8004ac82a90d7b46664da8da674919d3e2189c332a1f78" + } + ], + "type": "distribution", + "url": "file://.../tests/_data/infiles/_helpers/local_pckages/b/dist/package_b-23.42-py3-none-any.whl" + } + ], + "licenses": [ + { + "license": { + "id": "Apache-2.0" + } + } + ], + "name": "package-b", + "type": "library", + "version": "23.42" + }, + { + "bom-ref": "package-c==23.42", + "description": "some package C", + "externalReferences": [ + { + "comment": "PackageSource: Archive", + "hashes": [ + { + "alg": "SHA-256", + "content": "c1ac59f18ed20f2e651a37f74134ade2a396e27513ef1c73461873c49058f641" + } + ], + "type": "distribution", + "url": "file://.../tests/_data/infiles/_helpers/local_pckages/c/dist/package_c-23.42-py3-none-any.whl" + } + ], + "licenses": [ + { + "expression": "Apache-2.0 OR MIT" + } + ], + "name": "package-c", + "type": "library", + "version": "23.42" + } + ], + "dependencies": [ + { + "ref": "package-a==23.42" + }, + { + "ref": "package-b==23.42" + }, + { + "ref": "package-c==23.42" + }, + { + "ref": "root-component" + } + ], + "metadata": { + "component": { + "bom-ref": "root-component", + "description": "with licenses as text, instead of SPDX ID/Expression", + "licenses": [ + { + "license": { + "name": "declared license of 'with-license-text'", + "text": { + "content": "This is the license text of this component.\nIt is expected to be available in a SBOM.", + "contentType": "text/plain" + } + } + } + ], + "name": "with-license-text", + "type": "application", + "version": "0.1.0" + }, + "properties": [ + { + "name": "cdx:reproducible", + "value": "true" + } + ], + "tools": [ + { + "externalReferences": [ ], + "name": "cyclonedx-python-lib", + "vendor": "CycloneDX", + "version": "libVersion-testing" + } + ] + }, + "version": 1, + "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.4" +} \ No newline at end of file diff --git a/tests/_data/snapshots/environment/plain_with-license-text_1.4.xml.bin b/tests/_data/snapshots/environment/plain_with-license-text_1.4.xml.bin new file mode 100644 index 00000000..f4b58571 --- /dev/null +++ b/tests/_data/snapshots/environment/plain_with-license-text_1.4.xml.bin @@ -0,0 +1,123 @@ + + + + + + CycloneDX + cyclonedx-bom + thisVersion-testing + + + https://github.com/CycloneDX/cyclonedx-python/actions + + + https://pypi.org/project/cyclonedx-bom/ + + + https://cyclonedx-bom-tool.readthedocs.io/ + + + https://github.com/CycloneDX/cyclonedx-python/issues + + + https://github.com/CycloneDX/cyclonedx-python/blob/main/LICENSE + + + https://github.com/CycloneDX/cyclonedx-python/blob/main/CHANGELOG.md + + + https://github.com/CycloneDX/cyclonedx-python/ + + + https://github.com/CycloneDX/cyclonedx-python/#readme + + + + + CycloneDX + cyclonedx-python-lib + libVersion-testing + + + + + with-license-text + 0.1.0 + with licenses as text, instead of SPDX ID/Expression + + + declared license of 'with-license-text' + This is the license text of this component. +It is expected to be available in a SBOM. + + + + + true + + + + + package-a + 23.42 + some package A + + + declared license of 'package-a' + some license text + + + + + file://.../tests/_data/infiles/_helpers/local_pckages/a/dist/package_a-23.42-py3-none-any.whl + PackageSource: Archive + + 5c8da28603857d4073c67e751ba3cd526a7ef414135faecfec164e7d01be24be + + + + + + package-b + 23.42 + some package B + + + Apache-2.0 + + + + + file://.../tests/_data/infiles/_helpers/local_pckages/b/dist/package_b-23.42-py3-none-any.whl + PackageSource: Archive + + 583f7cb9db5c26194e8004ac82a90d7b46664da8da674919d3e2189c332a1f78 + + + + + + package-c + 23.42 + some package C + + Apache-2.0 OR MIT + + + + file://.../tests/_data/infiles/_helpers/local_pckages/c/dist/package_c-23.42-py3-none-any.whl + PackageSource: Archive + + c1ac59f18ed20f2e651a37f74134ade2a396e27513ef1c73461873c49058f641 + + + + + + + + + + + + diff --git a/tests/_data/snapshots/environment/plain_with-license-text_1.5.json.bin b/tests/_data/snapshots/environment/plain_with-license-text_1.5.json.bin new file mode 100644 index 00000000..1215ff89 --- /dev/null +++ b/tests/_data/snapshots/environment/plain_with-license-text_1.5.json.bin @@ -0,0 +1,139 @@ +{ + "components": [ + { + "bom-ref": "package-a==23.42", + "description": "some package A", + "externalReferences": [ + { + "comment": "PackageSource: Archive", + "hashes": [ + { + "alg": "SHA-256", + "content": "5c8da28603857d4073c67e751ba3cd526a7ef414135faecfec164e7d01be24be" + } + ], + "type": "distribution", + "url": "file://.../tests/_data/infiles/_helpers/local_pckages/a/dist/package_a-23.42-py3-none-any.whl" + } + ], + "licenses": [ + { + "license": { + "name": "declared license of 'package-a'", + "text": { + "content": "some license text", + "contentType": "text/plain" + } + } + } + ], + "name": "package-a", + "type": "library", + "version": "23.42" + }, + { + "bom-ref": "package-b==23.42", + "description": "some package B", + "externalReferences": [ + { + "comment": "PackageSource: Archive", + "hashes": [ + { + "alg": "SHA-256", + "content": "583f7cb9db5c26194e8004ac82a90d7b46664da8da674919d3e2189c332a1f78" + } + ], + "type": "distribution", + "url": "file://.../tests/_data/infiles/_helpers/local_pckages/b/dist/package_b-23.42-py3-none-any.whl" + } + ], + "licenses": [ + { + "license": { + "id": "Apache-2.0" + } + } + ], + "name": "package-b", + "type": "library", + "version": "23.42" + }, + { + "bom-ref": "package-c==23.42", + "description": "some package C", + "externalReferences": [ + { + "comment": "PackageSource: Archive", + "hashes": [ + { + "alg": "SHA-256", + "content": "c1ac59f18ed20f2e651a37f74134ade2a396e27513ef1c73461873c49058f641" + } + ], + "type": "distribution", + "url": "file://.../tests/_data/infiles/_helpers/local_pckages/c/dist/package_c-23.42-py3-none-any.whl" + } + ], + "licenses": [ + { + "expression": "Apache-2.0 OR MIT" + } + ], + "name": "package-c", + "type": "library", + "version": "23.42" + } + ], + "dependencies": [ + { + "ref": "package-a==23.42" + }, + { + "ref": "package-b==23.42" + }, + { + "ref": "package-c==23.42" + }, + { + "ref": "root-component" + } + ], + "metadata": { + "component": { + "bom-ref": "root-component", + "description": "with licenses as text, instead of SPDX ID/Expression", + "licenses": [ + { + "license": { + "name": "declared license of 'with-license-text'", + "text": { + "content": "This is the license text of this component.\nIt is expected to be available in a SBOM.", + "contentType": "text/plain" + } + } + } + ], + "name": "with-license-text", + "type": "application", + "version": "0.1.0" + }, + "properties": [ + { + "name": "cdx:reproducible", + "value": "true" + } + ], + "tools": [ + { + "externalReferences": [ ], + "name": "cyclonedx-python-lib", + "vendor": "CycloneDX", + "version": "libVersion-testing" + } + ] + }, + "version": 1, + "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json", + "bomFormat": "CycloneDX", + "specVersion": "1.5" +} \ No newline at end of file diff --git a/tests/_data/snapshots/environment/plain_with-license-text_1.5.xml.bin b/tests/_data/snapshots/environment/plain_with-license-text_1.5.xml.bin new file mode 100644 index 00000000..71e31ea7 --- /dev/null +++ b/tests/_data/snapshots/environment/plain_with-license-text_1.5.xml.bin @@ -0,0 +1,123 @@ + + + + + + CycloneDX + cyclonedx-bom + thisVersion-testing + + + https://github.com/CycloneDX/cyclonedx-python/actions + + + https://pypi.org/project/cyclonedx-bom/ + + + https://cyclonedx-bom-tool.readthedocs.io/ + + + https://github.com/CycloneDX/cyclonedx-python/issues + + + https://github.com/CycloneDX/cyclonedx-python/blob/main/LICENSE + + + https://github.com/CycloneDX/cyclonedx-python/blob/main/CHANGELOG.md + + + https://github.com/CycloneDX/cyclonedx-python/ + + + https://github.com/CycloneDX/cyclonedx-python/#readme + + + + + CycloneDX + cyclonedx-python-lib + libVersion-testing + + + + + with-license-text + 0.1.0 + with licenses as text, instead of SPDX ID/Expression + + + declared license of 'with-license-text' + This is the license text of this component. +It is expected to be available in a SBOM. + + + + + true + + + + + package-a + 23.42 + some package A + + + declared license of 'package-a' + some license text + + + + + file://.../tests/_data/infiles/_helpers/local_pckages/a/dist/package_a-23.42-py3-none-any.whl + PackageSource: Archive + + 5c8da28603857d4073c67e751ba3cd526a7ef414135faecfec164e7d01be24be + + + + + + package-b + 23.42 + some package B + + + Apache-2.0 + + + + + file://.../tests/_data/infiles/_helpers/local_pckages/b/dist/package_b-23.42-py3-none-any.whl + PackageSource: Archive + + 583f7cb9db5c26194e8004ac82a90d7b46664da8da674919d3e2189c332a1f78 + + + + + + package-c + 23.42 + some package C + + Apache-2.0 OR MIT + + + + file://.../tests/_data/infiles/_helpers/local_pckages/c/dist/package_c-23.42-py3-none-any.whl + PackageSource: Archive + + c1ac59f18ed20f2e651a37f74134ade2a396e27513ef1c73461873c49058f641 + + + + + + + + + + + +